From 049832107ea9c6e5079a54dc0bdca504bcd8ea39 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Mon, 25 Jun 2012 16:33:44 +1000 Subject: [PATCH] Resync with broadcom drivers 5.100.138.20 and utilities. Do not use pre-compiled binary blob unless we have to, build them from source instead. nas, eapd and wl were used as binary blob, now build them from source Conflicts: release/src-rt/include/bcmnvram.h --- release/src-rt/bcm57xx/linux/757um.c | 6349 -------------------- release/src-rt/bcm57xx/linux/b57um.c | 64 +- release/src-rt/bcmcrypto/Makefile | 69 + release/src-rt/bcmcrypto/aes.c | 1198 ++++ release/src-rt/bcmcrypto/aes_vectors.h | 1066 ++++ release/src-rt/bcmcrypto/aeskeywrap.c | 291 + release/src-rt/bcmcrypto/aeskeywrap_vectors.h | 256 + .../src-rt/bcmcrypto/{prebuilt/.dummy => bcmccx.c} | 0 release/src-rt/bcmcrypto/bn.c | 5661 +++++++++++++++++ release/src-rt/bcmcrypto/bn_lcl.h | 451 ++ .../src-rt/bcmcrypto/{prebuilt/.dummy => ccx.c} | 0 release/src-rt/bcmcrypto/ccx.ref | 171 + release/src-rt/bcmcrypto/des.c | 655 ++ release/src-rt/bcmcrypto/dh.c | 617 ++ .../bcmcrypto/{prebuilt/.dummy => examccx.h} | 0 .../bcmcrypto/{prebuilt/.dummy => examppkt.h} | 0 release/src-rt/bcmcrypto/hmac.c | 136 + release/src-rt/bcmcrypto/hmac_sha256.c | 236 + release/src-rt/bcmcrypto/md32_common.h | 602 ++ release/src-rt/bcmcrypto/md4.c | 287 + release/src-rt/bcmcrypto/md5.c | 323 + release/src-rt/bcmcrypto/passhash.c | 274 + release/src-rt/bcmcrypto/passhash_vectors.h | 268 + release/src-rt/bcmcrypto/prebuilt/aes.o | Bin 7392 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/aeskeywrap.o | Bin 2768 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/bn.o | Bin 55964 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/dh.o | Bin 4216 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/hmac.o | Bin 1744 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/hmac_sha256.o | Bin 2824 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/md5.o | Bin 5564 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/passhash.o | Bin 3124 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/prf.o | Bin 3380 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/random.o | Bin 2444 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/rc4.o | Bin 1224 -> 0 bytes .../src-rt/bcmcrypto/prebuilt/rijndael-alg-fst.o | Bin 17664 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/sha1.o | Bin 3028 -> 0 bytes release/src-rt/bcmcrypto/prebuilt/sha256.o | Bin 14920 -> 0 bytes release/src-rt/bcmcrypto/prf.c | 353 ++ release/src-rt/bcmcrypto/prf_vectors.h | 143 + release/src-rt/bcmcrypto/random.c | 180 + release/src-rt/bcmcrypto/rc4.c | 114 + release/src-rt/bcmcrypto/rc4_vectors.h | 294 + release/src-rt/bcmcrypto/rijndael-alg-fst.c | 1539 +++++ release/src-rt/bcmcrypto/sha1.c | 522 ++ release/src-rt/bcmcrypto/sha256.c | 445 ++ release/src-rt/bcmcrypto/sms4.c | 1375 +++++ release/src-rt/bcmcrypto/tkhash.c | 301 + release/src-rt/bcmcrypto/tkhash_vectors.h | 171 + release/src-rt/bcmcrypto/tkmic.c | 88 + release/src-rt/bcmcrypto/wep.c | 86 + release/src-rt/emf/emf/emfc.c | 38 +- release/src-rt/emf/emfconf/Makefile | 2 +- release/src-rt/emf/emfconf/emfu.c | 4 +- release/src-rt/emf/emfconf/emfu.h | 4 +- release/src-rt/emf/emfconf/emfu_linux.c | 4 +- release/src-rt/emf/emfconf/emfu_linux.h | 4 +- release/src-rt/emf/igs/igsc.c | 8 +- release/src-rt/emf/igsconf/Makefile | 2 +- release/src-rt/emf/igsconf/igsu.c | 4 +- release/src-rt/emf/igsconf/igsu.h | 4 +- release/src-rt/emf/igsconf/igsu_linux.c | 4 +- release/src-rt/emf/igsconf/igsu_linux.h | 4 +- release/src-rt/include/UdpLib.h | 0 release/src-rt/include/aidmp.h | 0 release/src-rt/include/amemc_core.h | 152 + release/src-rt/include/arminc.h | 0 release/src-rt/include/bcm20xx.h | 1460 ----- release/src-rt/include/bcm_cfg.h | 0 release/src-rt/include/bcm_ndis.h | 0 release/src-rt/include/bcm_xdr.h | 0 release/src-rt/include/bcmcdc.h | 0 release/src-rt/include/bcmdefs.h | 10 +- release/src-rt/include/bcmdevs.h | 27 +- release/src-rt/include/bcmendian.h | 0 release/src-rt/include/bcmenet47xx.h | 0 release/src-rt/include/bcmenetmib.h | 0 release/src-rt/include/bcmenetphy.h | 2 - release/src-rt/include/bcmenetrxh.h | 0 release/src-rt/include/bcmgmacmib.h | 0 release/src-rt/include/bcmgmacrxh.h | 0 release/src-rt/include/bcmnvram.h | 0 release/src-rt/include/bcmotp.h | 0 release/src-rt/include/bcmparams.h | 4 +- release/src-rt/include/bcmperf.h | 0 release/src-rt/include/bcmrobo.h | 0 release/src-rt/include/bcmsdpcm.h | 0 release/src-rt/include/bcmsrom.h | 0 release/src-rt/include/bcmsrom_fmt.h | 1 + release/src-rt/include/bcmsrom_tbl.h | 51 +- release/src-rt/include/bcmstdlib.h | 0 release/src-rt/include/bcmutils.h | 3 + release/src-rt/include/bcmwifi.h | 0 release/src-rt/include/bcmwpa.h | 0 release/src-rt/include/bitfuncs.h | 0 release/src-rt/include/cfe_osl.h | 0 release/src-rt/include/code_pattern.h | 1 - release/src-rt/include/cyutils.h | 7 - release/src-rt/include/d11.h | 0 release/src-rt/include/dmemc_core.h | 0 release/src-rt/include/epivers.h | 0 release/src-rt/include/epivers.h.in | 0 release/src-rt/include/etioctl.h | 28 + release/src-rt/include/flash.h | 0 release/src-rt/include/flashutl.h | 0 release/src-rt/include/gmac_common.h | 0 release/src-rt/include/gmac_core.h | 0 release/src-rt/include/hndarm.h | 0 release/src-rt/include/hndchipc.h | 0 release/src-rt/include/hndcpu.h | 0 release/src-rt/include/hnddma.h | 0 release/src-rt/include/hndgige.h | 0 release/src-rt/include/hndjtagdefs.h | 0 release/src-rt/include/hndmips.h | 0 release/src-rt/include/hndpci.h | 2 + release/src-rt/include/hndpmu.h | 0 release/src-rt/include/hndrte.h | 0 release/src-rt/include/hndrte_arm.h | 0 release/src-rt/include/hndrte_armtrap.h | 0 release/src-rt/include/hndrte_cons.h | 0 release/src-rt/include/hndrte_lbuf.h | 0 release/src-rt/include/hndrte_osl.h | 0 release/src-rt/include/hndrte_trap.h | 0 release/src-rt/include/hndsoc.h | 0 release/src-rt/include/hndtcam.h | 0 release/src-rt/include/libsmbclient.h | 3170 ++++++++++ release/src-rt/include/linux_gpio.h | 0 release/src-rt/include/linux_osl.h | 69 +- release/src-rt/include/linuxver.h | 0 release/src-rt/include/min_osl.h | 0 release/src-rt/include/miniopt.h | 0 release/src-rt/include/mips33_core.h | 0 release/src-rt/include/mips74k_core.h | 0 release/src-rt/include/mipsinc.h | 0 release/src-rt/include/ndiserrmap.h | 0 release/src-rt/include/nflash.h | 0 release/src-rt/include/nicpci.h | 0 release/src-rt/include/oidencap.h | 0 release/src-rt/include/osl.h | 0 release/src-rt/include/packed_section_end.h | 0 release/src-rt/include/packed_section_start.h | 0 release/src-rt/include/pci_core.h | 0 release/src-rt/include/pcicfg.h | 0 release/src-rt/include/pcie_core.h | 0 release/src-rt/include/proto/{202.3.h => 802.3.h} | 0 release/src-rt/include/proto/bcmip.h | 1 + release/src-rt/include/proto/{papol.h => eapol.h} | 0 release/src-rt/include/proto/mcmip.h | 148 - release/src-rt/include/qmath.h | 0 release/src-rt/include/sbchipc.h | 8 +- release/src-rt/include/sbconfig.h | 0 release/src-rt/include/sbgige.h | 0 release/src-rt/include/sbhndcpu.h | 0 release/src-rt/include/sbhnddma.h | 0 release/src-rt/include/sbhndpio.h | 0 release/src-rt/include/sbmemc.h | 0 release/src-rt/include/sbpcmcia.h | 0 release/src-rt/include/sbsdio.h | 0 release/src-rt/include/sbsdpcmdev.h | 0 release/src-rt/include/sbsdram.h | 0 release/src-rt/include/sbsocram.h | 0 release/src-rt/include/sbsprom.h | 0 release/src-rt/include/sbusbd.h | 0 release/src-rt/include/sflash.h | 0 release/src-rt/include/siutils.h | 1 + release/src-rt/include/trxhdr.h | 0 release/src-rt/include/typedefs.h | 10 +- release/src-rt/include/usbrdl.h | 0 release/src-rt/include/usbstd.h | 0 release/src-rt/include/wlc_extlog_idstr.h | 0 release/src-rt/include/wlioctl.h | 36 +- release/src-rt/include/wllmacctl.h | 0 release/src-rt/shared/aisdram.S | 456 +- release/src-rt/shared/aiutils.c | 93 +- release/src-rt/shared/bcm_rpc.c | 9 +- release/src-rt/shared/bcmotp.c | 5 +- release/src-rt/shared/bcmrobo.c | 0 release/src-rt/shared/flashutl.c | 2 +- release/src-rt/shared/hnddma.c | 8 + release/src-rt/shared/hndmips.c | 122 +- release/src-rt/shared/hndpci.c | 44 +- release/src-rt/shared/hndpmu.c | 78 +- release/src-rt/shared/linux_osl.c | 19 +- release/src-rt/shared/nvram/nvram.c | 181 +- release/src-rt/shared/nvram/nvram_ro.c | 229 - release/src-rt/shared/nvram/nvram_rw.c | 0 release/src-rt/shared/nvram/nvram_vx.c | 308 - release/src-rt/shared/siutils.c | 53 +- release/src-rt/shared/siutils_priv.h | 1 + release/src-rt/wl/mipsel-uclibc/eapd | Bin 37619 -> 0 bytes release/src-rt/wl/mipsel-uclibc/nas | Bin 77820 -> 0 bytes release/src-rt/wl/mipsel-uclibc/wl | Bin 360057 -> 0 bytes release/src-rt/wlconf/wlconf.c | 38 +- release/src/router/prebuilt/wl_exe.o | Bin 0 -> 264560 bytes 193 files changed, 22527 insertions(+), 8977 deletions(-) delete mode 100644 release/src-rt/bcm57xx/linux/757um.c mode change 100644 => 100755 release/src-rt/bcm57xx/linux/b57um.c create mode 100755 release/src-rt/bcmcrypto/Makefile create mode 100755 release/src-rt/bcmcrypto/aes.c create mode 100755 release/src-rt/bcmcrypto/aes_vectors.h create mode 100755 release/src-rt/bcmcrypto/aeskeywrap.c create mode 100755 release/src-rt/bcmcrypto/aeskeywrap_vectors.h copy release/src-rt/bcmcrypto/{prebuilt/.dummy => bcmccx.c} (100%) mode change 100644 => 100755 create mode 100755 release/src-rt/bcmcrypto/bn.c create mode 100755 release/src-rt/bcmcrypto/bn_lcl.h copy release/src-rt/bcmcrypto/{prebuilt/.dummy => ccx.c} (100%) mode change 100644 => 100755 create mode 100755 release/src-rt/bcmcrypto/ccx.ref create mode 100755 release/src-rt/bcmcrypto/des.c create mode 100755 release/src-rt/bcmcrypto/dh.c copy release/src-rt/bcmcrypto/{prebuilt/.dummy => examccx.h} (100%) mode change 100644 => 100755 rename release/src-rt/bcmcrypto/{prebuilt/.dummy => examppkt.h} (100%) mode change 100644 => 100755 create mode 100755 release/src-rt/bcmcrypto/hmac.c create mode 100755 release/src-rt/bcmcrypto/hmac_sha256.c create mode 100755 release/src-rt/bcmcrypto/md32_common.h create mode 100755 release/src-rt/bcmcrypto/md4.c create mode 100755 release/src-rt/bcmcrypto/md5.c create mode 100755 release/src-rt/bcmcrypto/passhash.c create mode 100755 release/src-rt/bcmcrypto/passhash_vectors.h delete mode 100644 release/src-rt/bcmcrypto/prebuilt/aes.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/aeskeywrap.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/bn.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/dh.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/hmac.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/hmac_sha256.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/md5.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/passhash.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/prf.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/random.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/rc4.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/rijndael-alg-fst.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/sha1.o delete mode 100644 release/src-rt/bcmcrypto/prebuilt/sha256.o create mode 100755 release/src-rt/bcmcrypto/prf.c create mode 100755 release/src-rt/bcmcrypto/prf_vectors.h create mode 100755 release/src-rt/bcmcrypto/random.c create mode 100755 release/src-rt/bcmcrypto/rc4.c create mode 100755 release/src-rt/bcmcrypto/rc4_vectors.h create mode 100755 release/src-rt/bcmcrypto/rijndael-alg-fst.c create mode 100755 release/src-rt/bcmcrypto/sha1.c create mode 100755 release/src-rt/bcmcrypto/sha256.c create mode 100755 release/src-rt/bcmcrypto/sms4.c create mode 100755 release/src-rt/bcmcrypto/tkhash.c create mode 100755 release/src-rt/bcmcrypto/tkhash_vectors.h create mode 100755 release/src-rt/bcmcrypto/tkmic.c create mode 100755 release/src-rt/bcmcrypto/wep.c mode change 100644 => 100755 release/src-rt/emf/emf/emfc.c mode change 100644 => 100755 release/src-rt/emf/emfconf/Makefile mode change 100644 => 100755 release/src-rt/emf/emfconf/emfu.c mode change 100644 => 100755 release/src-rt/emf/emfconf/emfu.h mode change 100644 => 100755 release/src-rt/emf/emfconf/emfu_linux.c mode change 100644 => 100755 release/src-rt/emf/emfconf/emfu_linux.h mode change 100644 => 100755 release/src-rt/emf/igs/igsc.c mode change 100644 => 100755 release/src-rt/emf/igsconf/Makefile mode change 100644 => 100755 release/src-rt/emf/igsconf/igsu.c mode change 100644 => 100755 release/src-rt/emf/igsconf/igsu.h mode change 100644 => 100755 release/src-rt/emf/igsconf/igsu_linux.c mode change 100644 => 100755 release/src-rt/emf/igsconf/igsu_linux.h mode change 100644 => 100755 release/src-rt/include/UdpLib.h mode change 100644 => 100755 release/src-rt/include/aidmp.h create mode 100755 release/src-rt/include/amemc_core.h mode change 100644 => 100755 release/src-rt/include/arminc.h delete mode 100644 release/src-rt/include/bcm20xx.h mode change 100644 => 100755 release/src-rt/include/bcm_cfg.h mode change 100644 => 100755 release/src-rt/include/bcm_ndis.h mode change 100644 => 100755 release/src-rt/include/bcm_xdr.h mode change 100644 => 100755 release/src-rt/include/bcmcdc.h mode change 100644 => 100755 release/src-rt/include/bcmdefs.h mode change 100644 => 100755 release/src-rt/include/bcmdevs.h mode change 100644 => 100755 release/src-rt/include/bcmendian.h mode change 100644 => 100755 release/src-rt/include/bcmenet47xx.h mode change 100644 => 100755 release/src-rt/include/bcmenetmib.h mode change 100644 => 100755 release/src-rt/include/bcmenetphy.h mode change 100644 => 100755 release/src-rt/include/bcmenetrxh.h mode change 100644 => 100755 release/src-rt/include/bcmgmacmib.h mode change 100644 => 100755 release/src-rt/include/bcmgmacrxh.h mode change 100644 => 100755 release/src-rt/include/bcmnvram.h mode change 100644 => 100755 release/src-rt/include/bcmotp.h mode change 100644 => 100755 release/src-rt/include/bcmparams.h mode change 100644 => 100755 release/src-rt/include/bcmperf.h mode change 100644 => 100755 release/src-rt/include/bcmrobo.h mode change 100644 => 100755 release/src-rt/include/bcmsdpcm.h mode change 100644 => 100755 release/src-rt/include/bcmsrom.h mode change 100644 => 100755 release/src-rt/include/bcmsrom_fmt.h mode change 100644 => 100755 release/src-rt/include/bcmsrom_tbl.h mode change 100644 => 100755 release/src-rt/include/bcmstdlib.h mode change 100644 => 100755 release/src-rt/include/bcmutils.h mode change 100644 => 100755 release/src-rt/include/bcmwifi.h mode change 100644 => 100755 release/src-rt/include/bcmwpa.h mode change 100644 => 100755 release/src-rt/include/bitfuncs.h mode change 100644 => 100755 release/src-rt/include/cfe_osl.h delete mode 100644 release/src-rt/include/code_pattern.h delete mode 100644 release/src-rt/include/cyutils.h mode change 100644 => 100755 release/src-rt/include/d11.h mode change 100644 => 100755 release/src-rt/include/dmemc_core.h mode change 100644 => 100755 release/src-rt/include/epivers.h mode change 100644 => 100755 release/src-rt/include/epivers.h.in mode change 100644 => 100755 release/src-rt/include/etioctl.h mode change 100644 => 100755 release/src-rt/include/flash.h mode change 100644 => 100755 release/src-rt/include/flashutl.h mode change 100644 => 100755 release/src-rt/include/gmac_common.h mode change 100644 => 100755 release/src-rt/include/gmac_core.h mode change 100644 => 100755 release/src-rt/include/hndarm.h mode change 100644 => 100755 release/src-rt/include/hndchipc.h mode change 100644 => 100755 release/src-rt/include/hndcpu.h mode change 100644 => 100755 release/src-rt/include/hnddma.h mode change 100644 => 100755 release/src-rt/include/hndgige.h mode change 100644 => 100755 release/src-rt/include/hndjtagdefs.h mode change 100644 => 100755 release/src-rt/include/hndmips.h mode change 100644 => 100755 release/src-rt/include/hndpci.h mode change 100644 => 100755 release/src-rt/include/hndpmu.h mode change 100644 => 100755 release/src-rt/include/hndrte.h mode change 100644 => 100755 release/src-rt/include/hndrte_arm.h mode change 100644 => 100755 release/src-rt/include/hndrte_armtrap.h mode change 100644 => 100755 release/src-rt/include/hndrte_cons.h mode change 100644 => 100755 release/src-rt/include/hndrte_lbuf.h mode change 100644 => 100755 release/src-rt/include/hndrte_osl.h mode change 100644 => 100755 release/src-rt/include/hndrte_trap.h mode change 100644 => 100755 release/src-rt/include/hndsoc.h mode change 100644 => 100755 release/src-rt/include/hndtcam.h create mode 100755 release/src-rt/include/libsmbclient.h mode change 100644 => 100755 release/src-rt/include/linux_gpio.h mode change 100644 => 100755 release/src-rt/include/linux_osl.h mode change 100644 => 100755 release/src-rt/include/linuxver.h mode change 100644 => 100755 release/src-rt/include/min_osl.h mode change 100644 => 100755 release/src-rt/include/miniopt.h mode change 100644 => 100755 release/src-rt/include/mips33_core.h mode change 100644 => 100755 release/src-rt/include/mips74k_core.h mode change 100644 => 100755 release/src-rt/include/mipsinc.h mode change 100644 => 100755 release/src-rt/include/ndiserrmap.h mode change 100644 => 100755 release/src-rt/include/nflash.h mode change 100644 => 100755 release/src-rt/include/nicpci.h mode change 100644 => 100755 release/src-rt/include/oidencap.h mode change 100644 => 100755 release/src-rt/include/osl.h mode change 100644 => 100755 release/src-rt/include/packed_section_end.h mode change 100644 => 100755 release/src-rt/include/packed_section_start.h mode change 100644 => 100755 release/src-rt/include/pci_core.h mode change 100644 => 100755 release/src-rt/include/pcicfg.h mode change 100644 => 100755 release/src-rt/include/pcie_core.h rename release/src-rt/include/proto/{202.3.h => 802.3.h} (100%) mode change 100644 => 100755 mode change 100644 => 100755 release/src-rt/include/proto/bcmip.h rename release/src-rt/include/proto/{papol.h => eapol.h} (100%) mode change 100644 => 100755 delete mode 100644 release/src-rt/include/proto/mcmip.h mode change 100644 => 100755 release/src-rt/include/qmath.h mode change 100644 => 100755 release/src-rt/include/sbchipc.h mode change 100644 => 100755 release/src-rt/include/sbconfig.h mode change 100644 => 100755 release/src-rt/include/sbgige.h mode change 100644 => 100755 release/src-rt/include/sbhndcpu.h mode change 100644 => 100755 release/src-rt/include/sbhnddma.h mode change 100644 => 100755 release/src-rt/include/sbhndpio.h mode change 100644 => 100755 release/src-rt/include/sbmemc.h mode change 100644 => 100755 release/src-rt/include/sbpcmcia.h mode change 100644 => 100755 release/src-rt/include/sbsdio.h mode change 100644 => 100755 release/src-rt/include/sbsdpcmdev.h mode change 100644 => 100755 release/src-rt/include/sbsdram.h mode change 100644 => 100755 release/src-rt/include/sbsocram.h mode change 100644 => 100755 release/src-rt/include/sbsprom.h mode change 100644 => 100755 release/src-rt/include/sbusbd.h mode change 100644 => 100755 release/src-rt/include/sflash.h mode change 100644 => 100755 release/src-rt/include/siutils.h mode change 100644 => 100755 release/src-rt/include/trxhdr.h mode change 100644 => 100755 release/src-rt/include/typedefs.h mode change 100644 => 100755 release/src-rt/include/usbrdl.h mode change 100644 => 100755 release/src-rt/include/usbstd.h mode change 100644 => 100755 release/src-rt/include/wlc_extlog_idstr.h mode change 100644 => 100755 release/src-rt/include/wlioctl.h mode change 100644 => 100755 release/src-rt/include/wllmacctl.h mode change 100644 => 100755 release/src-rt/shared/aisdram.S mode change 100644 => 100755 release/src-rt/shared/aiutils.c mode change 100644 => 100755 release/src-rt/shared/bcm_rpc.c mode change 100644 => 100755 release/src-rt/shared/bcmotp.c mode change 100644 => 100755 release/src-rt/shared/bcmrobo.c mode change 100644 => 100755 release/src-rt/shared/flashutl.c mode change 100644 => 100755 release/src-rt/shared/hnddma.c mode change 100644 => 100755 release/src-rt/shared/hndmips.c mode change 100644 => 100755 release/src-rt/shared/hndpci.c mode change 100644 => 100755 release/src-rt/shared/hndpmu.c mode change 100644 => 100755 release/src-rt/shared/linux_osl.c mode change 100644 => 100755 release/src-rt/shared/nvram/nvram.c delete mode 100644 release/src-rt/shared/nvram/nvram_ro.c mode change 100644 => 100755 release/src-rt/shared/nvram/nvram_rw.c delete mode 100644 release/src-rt/shared/nvram/nvram_vx.c mode change 100644 => 100755 release/src-rt/shared/siutils.c mode change 100644 => 100755 release/src-rt/shared/siutils_priv.h delete mode 100755 release/src-rt/wl/mipsel-uclibc/eapd delete mode 100755 release/src-rt/wl/mipsel-uclibc/nas delete mode 100755 release/src-rt/wl/mipsel-uclibc/wl mode change 100644 => 100755 release/src-rt/wlconf/wlconf.c create mode 100755 release/src/router/prebuilt/wl_exe.o diff --git a/release/src-rt/bcm57xx/linux/757um.c b/release/src-rt/bcm57xx/linux/757um.c deleted file mode 100644 index 4812ed15b8..0000000000 --- a/release/src-rt/bcm57xx/linux/757um.c +++ /dev/null @@ -1,6349 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/******************************************************************************/ - -/* $Id: b57um.c,v 1.34.10.1 2010-10-09 01:46:48 Exp $ */ - -char bcm5700_driver[] = "bcm5700"; -char bcm5700_version[] = "8.3.14"; -char bcm5700_date[] = "(11/2/05)"; - -#define B57UM -#include "mm.h" - -#include "typedefs.h" -#include -#include "osl.h" -#include "bcmdefs.h" -#include "bcmdevs.h" -#include "bcmutils.h" -#include "hndsoc.h" -#include "siutils.h" -#include "hndgige.h" -#include "etioctl.h" -#include "bcmrobo.h" - -/* this is needed to get good and stable performances */ -#define EXTRA_HDR BCMEXTRAHDROOM - -/* A few user-configurable values. */ - -#define MAX_UNITS 16 -/* Used to pass the full-duplex flag, etc. */ -static int line_speed[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static int auto_speed[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int full_duplex[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int rx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int tx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int auto_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -static int mtu[MAX_UNITS] = {1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500}; /* Jumbo MTU for interfaces. */ -#endif -static int tx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int rx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -static int scatter_gather[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - -#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT -static unsigned int tx_pkt_desc_cnt[MAX_UNITS] = - {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, - TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, - TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, - TX_DESC_CNT}; - -#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT -static unsigned int rx_std_desc_cnt[MAX_UNITS] = - {RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT, - RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT, - RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT, - RX_DESC_CNT }; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT -static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] = - {JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, - JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, - JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, - JBO_DESC_CNT }; -#endif - -#ifdef BCM_INT_COAL -#ifdef BCM_NAPI_RXPOLL -static unsigned int adaptive_coalesce[MAX_UNITS] = - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -#else -static unsigned int adaptive_coalesce[MAX_UNITS] = - {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -#endif - -#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS -static unsigned int rx_coalesce_ticks[MAX_UNITS] = - {RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK, - RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK, - RX_COAL_TK,RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK, - RX_COAL_TK}; - -#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES -static unsigned int rx_max_coalesce_frames[MAX_UNITS] = - {RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM, - RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM, - RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM, - RX_COAL_FM}; - -#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS -static unsigned int tx_coalesce_ticks[MAX_UNITS] = - {TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK, - TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK, - TX_COAL_TK,TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK, - TX_COAL_TK}; - -#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES -static unsigned int tx_max_coalesce_frames[MAX_UNITS] = - {TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM, - TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM, - TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM, - TX_COAL_FM}; - -#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS -static unsigned int stats_coalesce_ticks[MAX_UNITS] = - {ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK, - ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK, - ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK, - ST_COAL_TK,}; - -#endif -#ifdef BCM_WOL -static int enable_wol[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -#endif -#ifdef BCM_TSO -static int enable_tso[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; -#endif -#ifdef BCM_NIC_SEND_BD -static int nic_tx_bd[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -#endif -#ifdef BCM_ASF -static int vlan_tag_mode[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -#endif -static int delay_link[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static int disable_d3hot[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) -static int disable_msi[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static int bcm_msi_chipset_bug = 0; -#endif - -#define BCM_TIMER_GRANULARITY (1000000 / HZ) - -/* Hack to hook the data path to the BCM WL dirver */ -#ifdef BCM_WL_EMULATOR -#include "bcmnvram.h" -#include "wl_bcm57emu.h" -#ifdef SKB_MANAGER -int skb_old_alloc = 0; -#endif -#endif /* BCM_WL_EMULATOR */ - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (2*HZ) - -#if (LINUX_VERSION_CODE < 0x02030d) -#define pci_resource_start(dev, bar) (dev->base_address[bar] & PCI_BASE_ADDRESS_MEM_MASK) -#elif (LINUX_VERSION_CODE < 0x02032b) -#define pci_resource_start(dev, bar) (dev->resource[bar] & PCI_BASE_ADDRESS_MEM_MASK) -#endif - -#if (LINUX_VERSION_CODE < 0x02032b) -#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb) -#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy); mark_bh(NET_BH) -#define netif_stop_queue(dev) set_bit(0, &dev->tbusy) - -static inline void netif_start_queue(struct net_device *dev) -{ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; -} - -#define netif_queue_stopped(dev) dev->tbusy -#define netif_running(dev) dev->start - -static inline void tasklet_schedule(struct tasklet_struct *tasklet) -{ - queue_task(tasklet, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static inline void tasklet_init(struct tasklet_struct *tasklet, - void (*func)(unsigned long), - unsigned long data) -{ - tasklet->next = NULL; - tasklet->sync = 0; - tasklet->routine = (void (*)(void *))func; - tasklet->data = (void *)data; -} - -#define tasklet_kill(tasklet) - -#endif - -#if (LINUX_VERSION_CODE < 0x020300) -struct pci_device_id { - unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ - unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ - unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ - unsigned long driver_data; /* Data private to the driver */ -}; - -#define PCI_ANY_ID 0 - -#define pci_set_drvdata(pdev, dev) -#define pci_get_drvdata(pdev) 0 - -#define pci_enable_device(pdev) 0 - -#define __devinit __init -#define __devinitdata __initdata -#define __devexit - -#define SET_MODULE_OWNER(dev) -#define MODULE_DEVICE_TABLE(pci, pci_tbl) - -#endif - -#if (LINUX_VERSION_CODE < 0x020411) -#ifndef __devexit_p -#define __devexit_p(x) x -#endif -#endif - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(license) -#endif - -#ifndef IRQ_RETVAL -typedef void irqreturn_t; -#define IRQ_RETVAL(x) -#endif - -#if (LINUX_VERSION_CODE < 0x02032a) -static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, - dma_addr_t *dma_handle) -{ - void *virt_ptr; - - /* Maximum in slab.c */ - if (size > 131072) - return 0; - - virt_ptr = kmalloc(size, GFP_KERNEL); - *dma_handle = virt_to_bus(virt_ptr); - return virt_ptr; -} -#define pci_free_consistent(dev, size, ptr, dma_ptr) kfree(ptr) - -#endif /*#if (LINUX_VERSION_CODE < 0x02032a) */ - - -#if (LINUX_VERSION_CODE < 0x02040d) - -#if (LINUX_VERSION_CODE >= 0x020409) && defined(RED_HAT_LINUX_KERNEL) - -#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL) -#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL) - -#else -/* pci_set_dma_mask is using dma_addr_t */ - -#define BCM_32BIT_DMA_MASK ((dma_addr_t) 0xffffffff) -#define BCM_64BIT_DMA_MASK ((dma_addr_t) 0xffffffff) - -#endif - -#else /* (LINUX_VERSION_CODE < 0x02040d) */ - -#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL) -#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL) -#endif - -#if (LINUX_VERSION_CODE < 0x020329) -#define pci_set_dma_mask(pdev, mask) (0) -#else -#if (LINUX_VERSION_CODE < 0x020403) -int -pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) -{ - if(! pci_dma_supported(dev, mask)) - return -EIO; - - dev->dma_mask = mask; - - return 0; -} -#endif -#endif - -#if (LINUX_VERSION_CODE < 0x020547) -#define pci_set_consistent_dma_mask(pdev, mask) (0) -#endif - -#if (LINUX_VERSION_CODE < 0x020402) -#define pci_request_regions(pdev, name) (0) -#define pci_release_regions(pdev) -#endif - -#if !defined(spin_is_locked) -#define spin_is_locked(lock) (test_bit(0,(lock))) -#endif - -#define BCM5700_LOCK(pUmDevice, flags) \ - if ((pUmDevice)->do_global_lock) { \ - spin_lock_irqsave(&(pUmDevice)->global_lock, flags); \ - } - -#define BCM5700_UNLOCK(pUmDevice, flags) \ - if ((pUmDevice)->do_global_lock) { \ - spin_unlock_irqrestore(&(pUmDevice)->global_lock, flags);\ - } - -inline void -bcm5700_intr_lock(PUM_DEVICE_BLOCK pUmDevice) -{ - if (pUmDevice->do_global_lock) { - spin_lock(&pUmDevice->global_lock); - } -} - -inline void -bcm5700_intr_unlock(PUM_DEVICE_BLOCK pUmDevice) -{ - if (pUmDevice->do_global_lock) { - spin_unlock(&pUmDevice->global_lock); - } -} - -void -bcm5700_intr_off(PUM_DEVICE_BLOCK pUmDevice) -{ - atomic_inc(&pUmDevice->intr_sem); - LM_DisableInterrupt(&pUmDevice->lm_dev); -#if (LINUX_VERSION_CODE >= 0x2051c) - synchronize_irq(pUmDevice->dev->irq); -#else - synchronize_irq(); -#endif - LM_DisableInterrupt(&pUmDevice->lm_dev); -} - -void -bcm5700_intr_on(PUM_DEVICE_BLOCK pUmDevice) -{ - if (atomic_dec_and_test(&pUmDevice->intr_sem)) { - LM_EnableInterrupt(&pUmDevice->lm_dev); - } -} - -/* - * Broadcom NIC Extension support - * -ffan - */ -#ifdef NICE_SUPPORT -#include "nicext.h" - -typedef struct { - ushort tag; - ushort signature; -} vlan_tag_t; - -#endif /* NICE_SUPPORT */ - -int MM_Packet_Desc_Size = sizeof(UM_PACKET); - -#if defined(MODULE) -MODULE_AUTHOR("Michael Chan and Gary Zambrano "); -MODULE_DESCRIPTION("BCM5700 Driver"); -MODULE_LICENSE("GPL"); - -#if (LINUX_VERSION_CODE < 0x020605) - -MODULE_PARM(debug, "i"); -MODULE_PARM(msglevel, "i"); -MODULE_PARM(line_speed, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(auto_speed, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -MODULE_PARM(tx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(scatter_gather, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_std_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#ifdef BCM_INT_COAL -MODULE_PARM(adaptive_coalesce, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(tx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(tx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(stats_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#ifdef BCM_WOL -MODULE_PARM(enable_wol, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#ifdef BCM_TSO -MODULE_PARM(enable_tso, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#ifdef BCM_NIC_SEND_BD -MODULE_PARM(nic_tx_bd, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#ifdef BCM_ASF -MODULE_PARM(vlan_tag_mode, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -MODULE_PARM(delay_link, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(disable_d3hot, "1-" __MODULE_STRING(MAX_UNITS) "i"); - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) -MODULE_PARM(disable_msi, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif - -#else /* parms*/ - -#if (LINUX_VERSION_CODE >= 0x020605) && (LINUX_VERSION_CODE < 0x02060a) - -static int var; - -#define numvar var - -#endif - -#if (LINUX_VERSION_CODE >= 0x2060a) - -#define numvar NULL - -#endif - -module_param_array(line_speed, int, numvar, 0); -module_param_array(auto_speed, int, numvar, 0); -module_param_array(full_duplex, int, numvar, 0); -module_param_array(rx_flow_control, int, numvar, 0); -module_param_array(tx_flow_control, int, numvar, 0); -module_param_array(auto_flow_control, int, numvar, 0); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -module_param_array(mtu, int, numvar, 0); -#endif -module_param_array(tx_checksum, int, numvar, 0); -module_param_array(rx_checksum, int, numvar, 0); -module_param_array(scatter_gather, int, numvar, 0); -module_param_array(tx_pkt_desc_cnt, int, numvar, 0); -module_param_array(rx_std_desc_cnt, int, numvar, 0); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -module_param_array(rx_jumbo_desc_cnt, int, numvar, 0); -#endif -#ifdef BCM_INT_COAL -module_param_array(adaptive_coalesce, int, numvar, 0); -module_param_array(rx_coalesce_ticks, int, numvar, 0); -module_param_array(rx_max_coalesce_frames, int, numvar, 0); -module_param_array(tx_coalesce_ticks, int, numvar, 0); -module_param_array(tx_max_coalesce_frames, int, numvar, 0); -module_param_array(stats_coalesce_ticks, int, numvar, 0); -#endif -#ifdef BCM_WOL -module_param_array(enable_wol, int, numvar, 0); -#endif -#ifdef BCM_TSO -module_param_array(enable_tso, int, numvar, 0); -#endif -#ifdef BCM_NIC_SEND_BD -module_param_array(nic_tx_bd, int, numvar, 0); -#endif -#ifdef BCM_ASF -module_param_array(vlan_tag_mode, int, numvar, 0); -#endif -module_param_array(delay_link, int, numvar, 0); -module_param_array(disable_d3hot, int, numvar, 0); - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) -module_param_array(disable_msi, int, numvar, 0); -#endif - - -#endif /* params */ - - -#endif - -#define RUN_AT(x) (jiffies + (x)) - -char kernel_version[] = UTS_RELEASE; - -#define PCI_SUPPORT_VER2 - -#if !defined(CAP_NET_ADMIN) -#define capable(CAP_XXX) (suser()) -#endif - -#define tigon3_debug debug -#if TIGON3_DEBUG -static int tigon3_debug = TIGON3_DEBUG; -#else -static int tigon3_debug = 0; -#endif -static int msglevel = 0xdeadbeef; -int b57_msg_level; - -int bcm5700_open(struct net_device *dev); -STATIC void bcm5700_timer(unsigned long data); -STATIC void bcm5700_stats_timer(unsigned long data); -STATIC void bcm5700_reset(struct net_device *dev); -STATIC int bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -STATIC irqreturn_t bcm5700_interrupt(int irq, void *dev_instance); -#else -STATIC irqreturn_t bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#endif -#ifdef BCM_TASKLET -STATIC void bcm5700_tasklet(unsigned long data); -#endif -STATIC int bcm5700_close(struct net_device *dev); -STATIC struct net_device_stats *bcm5700_get_stats(struct net_device *dev); -STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -STATIC void bcm5700_do_rx_mode(struct net_device *dev); -STATIC void bcm5700_set_rx_mode(struct net_device *dev); -STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu); -#endif -#ifdef BCM_NAPI_RXPOLL -STATIC int bcm5700_poll(struct net_device *dev, int *budget); -#endif -STATIC int replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max); -STATIC int bcm5700_freemem(struct net_device *dev); -#ifdef NICE_SUPPORT -STATIC int bcm5700_freemem2(UM_DEVICE_BLOCK *pUmDevice, int index); -#endif -#ifdef BCM_INT_COAL -#ifndef BCM_NAPI_RXPOLL -STATIC int bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice); -#endif -#endif -STATIC void bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice); -STATIC int bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice); -#ifdef BCM_VLAN -STATIC void bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp); -STATIC void bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid); -#endif -void bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice); -void bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice); -void bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param, - char *param_name, int min, int max, int deflt); - -static int bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused); -static struct notifier_block bcm5700_reboot_notifier = { - bcm5700_notify_reboot, - NULL, - 0 -}; - -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) -STATIC void poll_bcm5700(struct net_device *dev); -#endif - -/* A list of all installed bcm5700 devices. */ -static struct net_device *root_tigon3_dev = NULL; - -#if defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) ||defined(CONFIG_PPC64) - -#ifdef NICE_SUPPORT -#if (LINUX_VERSION_CODE < 0x20500) -extern int register_ioctl32_conversion(unsigned int cmd, - int (*handler)(unsigned int, unsigned int, unsigned long, - struct file *)); -int unregister_ioctl32_conversion(unsigned int cmd); -#else -#include -#endif - -#define BCM_IOCTL32 1 - -atomic_t bcm5700_load_count = ATOMIC_INIT(0); - -static int -bcm5700_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *filep) -{ - struct ifreq rq; - struct net_device *tmp_dev = root_tigon3_dev; - int ret; - struct nice_req* nrq; - struct ifreq_nice32 { - char ifnr_name[16]; - __u32 cmd; - __u32 nrq1; - __u32 nrq2; - __u32 nrq3; - } nrq32; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (mm_copy_from_user(&nrq32, (char *) arg, 32)) - return -EFAULT; - - memcpy(rq.ifr_name, nrq32.ifnr_name, 16); - - nrq = (struct nice_req*) &rq.ifr_ifru; - nrq->cmd = nrq32.cmd; - if (nrq->cmd == NICE_CMD_GET_STATS_BLOCK) { - nrq->nrq_stats_useraddr = (void *) ((__u64) nrq32.nrq1); - nrq->nrq_stats_size = nrq32.nrq2; - } - else { - memcpy(&nrq->nrq_speed, &nrq32.nrq1, 12); - } - while (tmp_dev) { - if (strcmp(rq.ifr_name, tmp_dev->name) == 0) { - ret = bcm5700_ioctl(tmp_dev, &rq, cmd); - if (ret == 0) { - if (nrq->cmd == NICE_CMD_GET_STATS_BLOCK) - return ret; - - memcpy(&nrq32.nrq1, &nrq->nrq_speed, 12); - if (mm_copy_to_user((char *) arg, &nrq32, 32)) - return -EFAULT; - } - return ret; - } - tmp_dev = ((UM_DEVICE_BLOCK *)(tmp_dev->priv))->next_module; - } - return -ENODEV; -} -#endif /* NICE_SUPPORT */ -#endif - -typedef enum { - BCM5700A6 = 0, - BCM5700T6, - BCM5700A9, - BCM5700T9, - BCM5700, - BCM5701A5, - BCM5701T1, - BCM5701T8, - BCM5701A7, - BCM5701A10, - BCM5701A12, - BCM5701, - BCM5702, - BCM5703, - BCM5703A31, - BCM5703ARBUCKLE, - TC996T, - TC996ST, - TC996SSX, - TC996SX, - TC996BT, - TC997T, - TC997SX, - TC1000T, - TC1000BT, - TC940BR01, - TC942BR01, - TC998T, - TC998SX, - TC999T, - NC6770, - NC1020, - NC150T, - NC7760, - NC7761, - NC7770, - NC7771, - NC7780, - NC7781, - NC7772, - NC7782, - NC7783, - NC320T, - NC320I, - NC325I, - NC324I, - NC326I, - BCM5704CIOBE, - BCM5704, - BCM5704S, - BCM5705, - BCM5705M, - BCM5705F, - BCM5901, - BCM5782, - BCM5788, - BCM5789, - BCM5750, - BCM5750M, - BCM5720, - BCM5751, - BCM5751M, - BCM5751F, - BCM5721, - BCM5753, - BCM5753M, - BCM5753F, - BCM5781, - BCM5752, - BCM5752M, - BCM5714, - BCM5780, - BCM5780S, - BCM5715, - BCM4785, - BCM5903M, - UNK5788 -} board_t; - - -/* indexed by board_t, above */ -static struct { - char *name; -} board_info[] __devinitdata = { - { "Broadcom BCM5700 1000Base-T" }, - { "Broadcom BCM5700 1000Base-SX" }, - { "Broadcom BCM5700 1000Base-SX" }, - { "Broadcom BCM5700 1000Base-T" }, - { "Broadcom BCM5700" }, - { "Broadcom BCM5701 1000Base-T" }, - { "Broadcom BCM5701 1000Base-T" }, - { "Broadcom BCM5701 1000Base-T" }, - { "Broadcom BCM5701 1000Base-SX" }, - { "Broadcom BCM5701 1000Base-T" }, - { "Broadcom BCM5701 1000Base-T" }, - { "Broadcom BCM5701" }, - { "Broadcom BCM5702 1000Base-T" }, - { "Broadcom BCM5703 1000Base-T" }, - { "Broadcom BCM5703 1000Base-SX" }, - { "Broadcom B5703 1000Base-SX" }, - { "3Com 3C996 10/100/1000 Server NIC" }, - { "3Com 3C996 10/100/1000 Server NIC" }, - { "3Com 3C996 Gigabit Fiber-SX Server NIC" }, - { "3Com 3C996 Gigabit Fiber-SX Server NIC" }, - { "3Com 3C996B Gigabit Server NIC" }, - { "3Com 3C997 Gigabit Server NIC" }, - { "3Com 3C997 Gigabit Fiber-SX Server NIC" }, - { "3Com 3C1000 Gigabit NIC" }, - { "3Com 3C1000B-T 10/100/1000 PCI" }, - { "3Com 3C940 Gigabit LOM (21X21)" }, - { "3Com 3C942 Gigabit LOM (31X31)" }, - { "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" }, - { "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" }, - { "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" }, - { "HP NC6770 Gigabit Server Adapter" }, - { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" }, - { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" }, - { "HP NC7760 Gigabit Server Adapter" }, - { "HP NC7761 Gigabit Server Adapter" }, - { "HP NC7770 Gigabit Server Adapter" }, - { "HP NC7771 Gigabit Server Adapter" }, - { "HP NC7780 Gigabit Server Adapter" }, - { "HP NC7781 Gigabit Server Adapter" }, - { "HP NC7772 Gigabit Server Adapter" }, - { "HP NC7782 Gigabit Server Adapter" }, - { "HP NC7783 Gigabit Server Adapter" }, - { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" }, - { "HP ProLiant NC 320i PCI Express Gigabit Server Adapter" }, - { "HP NC325i Integrated Dual Port PCI Express Gigabit Server Adapter" }, - { "HP NC324i Integrated Dual Port PCI Express Gigabit Server Adapter" }, - { "HP NC326i Integrated Dual Port PCI Express Gigabit Server Adapter" }, - { "Broadcom BCM5704 CIOB-E 1000Base-T" }, - { "Broadcom BCM5704 1000Base-T" }, - { "Broadcom BCM5704 1000Base-SX" }, - { "Broadcom BCM5705 1000Base-T" }, - { "Broadcom BCM5705M 1000Base-T" }, - { "Broadcom 570x 10/100 Integrated Controller" }, - { "Broadcom BCM5901 100Base-TX" }, - { "Broadcom NetXtreme Gigabit Ethernet for hp" }, - { "Broadcom BCM5788 NetLink 1000Base-T" }, - { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" }, - { "Broadcom BCM5750 1000Base-T PCI" }, - { "Broadcom BCM5750M 1000Base-T PCI" }, - { "Broadcom BCM5720 1000Base-T PCI" }, - { "Broadcom BCM5751 1000Base-T PCI Express" }, - { "Broadcom BCM5751M 1000Base-T PCI Express" }, - { "Broadcom BCM5751F 100Base-TX PCI Express" }, - { "Broadcom BCM5721 1000Base-T PCI Express" }, - { "Broadcom BCM5753 1000Base-T PCI Express" }, - { "Broadcom BCM5753M 1000Base-T PCI Express" }, - { "Broadcom BCM5753F 100Base-TX PCI Express" }, - { "Broadcom BCM5781 NetLink 1000Base-T PCI Express" }, - { "Broadcom BCM5752 1000Base-T PCI Express" }, - { "Broadcom BCM5752M 1000Base-T PCI Express" }, - { "Broadcom BCM5714 1000Base-T " }, - { "Broadcom BCM5780 1000Base-T" }, - { "Broadcom BCM5780S 1000Base-SX" }, - { "Broadcom BCM5715 1000Base-T " }, - { "Broadcom BCM4785 10/100/1000 Integrated Controller" }, - { "Broadcom BCM5903M Gigabit Ethernet " }, - { "Unknown BCM5788 Gigabit Ethernet " }, - { 0 } - }; - -static struct pci_device_id bcm5700_pci_tbl[] __devinitdata = { - {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 }, - {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 }, - {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 }, - {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 }, - {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 }, - {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 }, - {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 }, - {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 }, - {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T }, - {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST }, - {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX }, - {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T }, - {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX }, - {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 }, - {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 }, - {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 }, - {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 }, - {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 }, - {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 }, - {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 }, - {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 }, - {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 }, - {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 }, - {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 }, - {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 }, - {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX }, - {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT }, - {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T }, - {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 }, - {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 }, - {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 }, - {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, - {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 }, - {0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 }, - {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 }, - {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, - {0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT }, - {0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, - {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 }, - {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, - {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 }, - {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 }, - {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, - {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 }, - {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, - {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 }, - {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 }, - {0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 }, - {0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 }, - {0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE }, - {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, - {0x14e4, 0x16c7, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, - {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 }, - {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 }, - {0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, - {0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 }, - {0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 }, - {0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 }, - {0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T }, - {0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T }, - {0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE }, - {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 }, - {0x14e4, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S }, - {0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S }, - {0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX }, - {0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S }, - {0x14e4, 0x1653, 0x0e11, 0x00e3, 0, 0, NC7761 }, - {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 }, - {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 }, - {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 }, - {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T }, - {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 }, - {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M }, - {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M }, - {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F }, - {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 }, - {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 }, - {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 }, - {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 }, - {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 }, - {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 }, - {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M }, - {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 }, - {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M }, - {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F }, - {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 }, - {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T }, - {0x14e4, 0x1659, 0x103c, 0x7032, 0, 0, NC320T }, - {0x14e4, 0x166a, 0x103c, 0x7035, 0, 0, NC325I }, - {0x14e4, 0x166b, 0x103c, 0x7036, 0, 0, NC325I }, - {0x14e4, 0x1668, 0x103c, 0x7039, 0, 0, NC324I }, - {0x14e4, 0x1669, 0x103c, 0x703a, 0, 0, NC324I }, - {0x14e4, 0x1678, 0x103c, 0x703e, 0, 0, NC326I }, - {0x14e4, 0x1679, 0x103c, 0x703c, 0, 0, NC326I }, - {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 }, - {0x14e4, 0x16f7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753 }, - {0x14e4, 0x16fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753M }, - {0x14e4, 0x16fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753F }, - {0x14e4, 0x16dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5781 }, - {0x14e4, 0x1600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752 }, - {0x14e4, 0x1601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752M }, - {0x14e4, 0x1668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5714 }, - {0x14e4, 0x166a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780 }, - {0x14e4, 0x166b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780S }, - {0x14e4, 0x1678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5715 }, - {0x14e4, 0x471f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM4785 }, - {0x14e4, 0x16ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5903M }, - {0x173b, 0x03ed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, UNK5788 }, - {0,} - }; - -MODULE_DEVICE_TABLE(pci, bcm5700_pci_tbl); - -#ifdef BCM_PROC_FS -extern int bcm5700_proc_create(void); -extern int bcm5700_proc_create_dev(struct net_device *dev); -extern int bcm5700_proc_remove_dev(struct net_device *dev); -extern int bcm5700_proc_remove_notifier(void); -#endif - -#if (LINUX_VERSION_CODE >= 0x2060a) - static struct pci_device_id pci_AMD762id[]={ - { PCI_DEVICE(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_FE_GATE_700C) }, - { } - }; -#endif - -static int sbgige = -1; - -/******************************************************************************* - ******************************************************************************* -*/ - -int get_csum_flag(LM_UINT32 ChipRevId) -{ - return NETIF_F_IP_CSUM; -} - -/******************************************************************************* - ******************************************************************************* - - This function returns true if the device passed to it is attached to an - ICH-ICH4. If the chip is not attached to an ICH, or is attached to an ICH5 - or newer, it returns false. - - This function determines which bridge it is attached to by scaning the pci - bus looking for bridge chips (hdr_type=1). When a bridge chip is detected, - the bridge's subordinate's secondary bus number is compared with this - devices bus number. If they match, then the device is attached to this - bridge. The bridge's device id is compared to a list of known device ids for - ICH-ICH4. Since many older ICH's (ICH2-ICH7) share the same device id, the - chip revision must also be checked to determine if the chip is older than an - ICH5. - - To scan the bus, one of two functions is used depending on the kernel - version. For 2.4 kernels, the pci_find_device function is used. This - function has been depricated in the 2.6 kernel and replaced with the - fucntion pci_get_device. The macro walk_pci_bus determines which function to - use when the driver is built. -*/ - -#if (LINUX_VERSION_CODE >= 0x2060a) -#define walk_pci_bus(d) while ((d = pci_get_device( \ - PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) - -#define unwalk_pci_bus(d) pci_dev_put(d) - -#else -#define walk_pci_bus(d) while ((d = pci_find_device( \ - PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) -#define unwalk_pci_bus(d) - -#endif - -#define ICH5_CHIP_VERSION 0xc0 - -static struct pci_device_id pci_ICHtable[] = { - {0x8086, 0x2418}, /* PCI_DEVICE_ID_INTEL_82801AA_8 */ - {0x8086, 0x2428}, /* PCI_DEVICE_ID_INTEL_82801AB_8 */ - {0x8086, 0x244e}, /* PCI_DEVICE_ID_INTEL_82801BA_6 */ - {0x8086, 0x2448}, /* PCI_DEVICE_ID_INTEL_82801BA_11 */ - {0, 0} -}; - -int attached_to_ICH4_or_older( struct pci_dev *pdev) -{ - struct pci_dev *tmp_pdev = NULL; - struct pci_device_id *ich_table; - u8 chip_rev; - - walk_pci_bus (tmp_pdev) { - if ((tmp_pdev->hdr_type == 1) && - (tmp_pdev->subordinate != NULL) && - (tmp_pdev->subordinate->secondary == pdev->bus->number)) { - - ich_table = pci_ICHtable; - - while (ich_table->vendor) { - if ((ich_table->vendor == tmp_pdev->vendor) && - (ich_table->device == tmp_pdev->device)) { - - pci_read_config_byte( tmp_pdev, - PCI_REVISION_ID, &chip_rev); - - if (chip_rev < ICH5_CHIP_VERSION) { - unwalk_pci_bus( tmp_pdev); - return 1; - } - } - ich_table++; - } - } - } - return 0; -} - -static int -__devinit bcm5700_init_board(struct pci_dev *pdev, struct net_device **dev_out, int board_idx) -{ - struct net_device *dev; - PUM_DEVICE_BLOCK pUmDevice; - PLM_DEVICE_BLOCK pDevice; - bool rgmii = FALSE; - si_t *sih = NULL; - int rc; - - *dev_out = NULL; - - /* dev zeroed in init_etherdev */ -#if (LINUX_VERSION_CODE >= 0x20600) - dev = alloc_etherdev(sizeof(*pUmDevice)); -#else - dev = init_etherdev(NULL, sizeof(*pUmDevice)); -#endif - if (dev == NULL) { - printk(KERN_ERR "%s: unable to alloc new ethernet\n", bcm5700_driver); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); -#if (LINUX_VERSION_CODE >= 0x20600) - SET_NETDEV_DEV(dev, &pdev->dev); -#endif - pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - - /* enable device (incl. PCI PM wakeup), and bus-mastering */ - rc = pci_enable_device(pdev); - if (rc) - goto err_out; - - /* init core specific stuff */ - if (pdev->device == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM471F)) { - sih = si_kattach(SI_OSH); - hndgige_init(sih, ++sbgige, &rgmii); - } - - rc = pci_request_regions(pdev, bcm5700_driver); - if (rc) { - if (!sih) - goto err_out; - printk(KERN_INFO "bcm5700_init_board: pci_request_regions returned error %d\n" - "This may be because the region is already requested by" - " the SMBus driver. Ignore the PCI error messages.\n", rc); - } - - pci_set_master(pdev); - - if (pci_set_dma_mask(pdev, BCM_64BIT_DMA_MASK) == 0) { - pUmDevice->using_dac = 1; - if (pci_set_consistent_dma_mask(pdev, BCM_64BIT_DMA_MASK) != 0) { - printk(KERN_ERR "pci_set_consistent_dma_mask failed\n"); - pci_release_regions(pdev); - goto err_out; - } - } else if (pci_set_dma_mask(pdev, BCM_32BIT_DMA_MASK) == 0) { - pUmDevice->using_dac = 0; - } else { - printk(KERN_ERR "System does not support DMA\n"); - pci_release_regions(pdev); - goto err_out; - } - - pUmDevice->dev = dev; - pUmDevice->pdev = pdev; - pUmDevice->mem_list_num = 0; - pUmDevice->next_module = root_tigon3_dev; - pUmDevice->index = board_idx; - pUmDevice->sih = (void *)sih; - root_tigon3_dev = dev; - - spin_lock_init(&pUmDevice->global_lock); - - spin_lock_init(&pUmDevice->undi_lock); - - spin_lock_init(&pUmDevice->phy_lock); - - pDevice = &pUmDevice->lm_dev; - pDevice->Flags = 0; - pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn); - pUmDevice->boardflags = getintvar(NULL, "boardflags"); - if (sih) { - if (pUmDevice->boardflags & BFL_ENETROBO) - pDevice->Flags |= ROBO_SWITCH_FLAG; - pDevice->Flags |= rgmii ? RGMII_MODE_FLAG : 0; - if ((sih->chip == BCM4785_CHIP_ID) && (sih->chiprev < 2)) - pDevice->Flags |= ONE_DMA_AT_ONCE_FLAG; - pDevice->Flags |= SB_CORE_FLAG; - if (sih->chip == BCM4785_CHIP_ID) - pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG; - } - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - if (board_idx < MAX_UNITS) { - bcm5700_validate_param_range(pUmDevice, &mtu[board_idx], "mtu", 1500, 9000, 1500); - dev->mtu = mtu[board_idx]; - } -#endif - - if (attached_to_ICH4_or_older(pdev)) { - pDevice->Flags |= UNDI_FIX_FLAG; - } - -#if (LINUX_VERSION_CODE >= 0x2060a) - if (pci_dev_present(pci_AMD762id)) { - pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG; - pDevice->Flags &= ~NIC_SEND_BD_FLAG; - } -#else - if (pci_find_device(0x1022, 0x700c, NULL)) { - /* AMD762 writes I/O out of order */ - /* Setting bit 1 in 762's register 0x4C still doesn't work */ - /* in all cases */ - pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG; - pDevice->Flags &= ~NIC_SEND_BD_FLAG; - } -#endif - if (LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) { - rc = -ENODEV; - goto err_out_unmap; - } - - if (pDevice->Flags & ROBO_SWITCH_FLAG) { - robo_info_t *robo; - - if ((robo = bcm_robo_attach(sih, pDevice, NULL, - robo_miird, robo_miiwr)) == NULL) { - B57_ERR(("robo_setup: failed to attach robo switch \n")); - goto robo_fail; - } - - if (bcm_robo_enable_device(robo)) { - B57_ERR(("robo_setup: failed to enable robo switch \n")); - goto robo_fail; - } - - /* Configure the switch to do VLAN */ - if ((pUmDevice->boardflags & BFL_ENETVLAN) && - bcm_robo_config_vlan(robo, pDevice->PermanentNodeAddress)) { - B57_ERR(("robo_setup: robo_config_vlan failed\n")); - goto robo_fail; - } - - /* Enable the switch */ - if (bcm_robo_enable_switch(robo)) { - B57_ERR(("robo_setup: robo_enable_switch failed\n")); -robo_fail: - bcm_robo_detach(robo); - rc = -ENODEV; - goto err_out_unmap; - } - pUmDevice->robo = (void *)robo; - } - - if ((pDevice->Flags & JUMBO_CAPABLE_FLAG) == 0) { - if (dev->mtu > 1500) { - dev->mtu = 1500; - printk(KERN_WARNING - "%s-%d: Jumbo mtu sizes not supported, using mtu=1500\n", - bcm5700_driver, pUmDevice->index); - } - } - - pUmDevice->do_global_lock = 0; - if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) { - /* The 5700 chip works best without interleaved register */ - /* accesses on certain machines. */ - pUmDevice->do_global_lock = 1; - } - - if ((T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5701) && - ((pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) == 0)) { - - pUmDevice->rx_buf_align = 0; - } else { - pUmDevice->rx_buf_align = 2; - } - dev->mem_start = pci_resource_start(pdev, 0); - dev->mem_end = dev->mem_start + sizeof(T3_STD_MEM_MAP); - dev->irq = pdev->irq; - - *dev_out = dev; - -#ifdef HNDCTF - pUmDevice->osh = osl_attach(pdev, PCI_BUS, FALSE); - - pUmDevice->cih = ctf_attach(pUmDevice->osh, dev->name, &b57_msg_level, NULL, NULL); - - ctf_dev_register(pUmDevice->cih, dev, FALSE); - ctf_enable(pUmDevice->cih, dev, TRUE); -#endif /* HNDCTF */ - - return 0; - -err_out_unmap: - pci_release_regions(pdev); - bcm5700_freemem(dev); - -err_out: -#if (LINUX_VERSION_CODE < 0x020600) - unregister_netdev(dev); - kfree(dev); -#else - free_netdev(dev); -#endif - return rc; -} - -static int __devinit -bcm5700_print_ver(void) -{ - printk(KERN_INFO "Broadcom Gigabit Ethernet Driver %s ", - bcm5700_driver); -#ifdef NICE_SUPPORT - printk("with Broadcom NIC Extension (NICE) "); -#endif - printk("ver. %s %s\n", bcm5700_version, bcm5700_date); - return 0; -} - -static int __devinit -bcm5700_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - PUM_DEVICE_BLOCK pUmDevice; - PLM_DEVICE_BLOCK pDevice; - int i; - static int board_idx = -1; - static int printed_version = 0; - struct pci_dev *pci_dev; - - board_idx++; - - if (!printed_version) { - bcm5700_print_ver(); -#ifdef BCM_PROC_FS - bcm5700_proc_create(); -#endif - printed_version = 1; - } - - i = bcm5700_init_board(pdev, &dev, board_idx); - if (i < 0) { - return i; - } - - if (dev == NULL) - return -ENOMEM; - -#ifdef BCM_IOCTL32 - if (atomic_read(&bcm5700_load_count) == 0) { - register_ioctl32_conversion(SIOCNICE, bcm5700_ioctl32); - } - atomic_inc(&bcm5700_load_count); -#endif - dev->open = bcm5700_open; - dev->hard_start_xmit = bcm5700_start_xmit; - dev->stop = bcm5700_close; - dev->get_stats = bcm5700_get_stats; - dev->set_multicast_list = bcm5700_set_rx_mode; - dev->do_ioctl = bcm5700_ioctl; - dev->set_mac_address = &bcm5700_set_mac_addr; -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - dev->change_mtu = &bcm5700_change_mtu; -#endif -#if (LINUX_VERSION_CODE >= 0x20400) - dev->tx_timeout = bcm5700_reset; - dev->watchdog_timeo = TX_TIMEOUT; -#endif -#ifdef BCM_VLAN - dev->vlan_rx_register = &bcm5700_vlan_rx_register; - dev->vlan_rx_kill_vid = &bcm5700_vlan_rx_kill_vid; -#endif -#ifdef BCM_NAPI_RXPOLL - dev->poll = bcm5700_poll; - dev->weight = 64; -#endif - - pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - - dev->base_addr = pci_resource_start(pdev, 0); - dev->irq = pdev->irq; -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) - dev->poll_controller = poll_bcm5700; -#endif - -#if (LINUX_VERSION_CODE >= 0x20600) - if ((i = register_netdev(dev))) { - printk(KERN_ERR "%s: Cannot register net device\n", - bcm5700_driver); - if (pUmDevice->lm_dev.pMappedMemBase) - iounmap(pUmDevice->lm_dev.pMappedMemBase); - pci_release_regions(pdev); - bcm5700_freemem(dev); - free_netdev(dev); - return i; - } -#endif - - - pci_set_drvdata(pdev, dev); - - memcpy(dev->dev_addr, pDevice->NodeAddress, 6); - pUmDevice->name = board_info[ent->driver_data].name, - printk(KERN_INFO "%s: %s found at mem %lx, IRQ %d, ", - dev->name, pUmDevice->name, dev->base_addr, - dev->irq); - printk("node addr "); - for (i = 0; i < 6; i++) { - printk("%2.2x", dev->dev_addr[i]); - } - printk("\n"); - - printk(KERN_INFO "%s: ", dev->name); - if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID) - printk("Broadcom BCM5400 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) - printk("Broadcom BCM5401 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID) - printk("Broadcom BCM5411 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5461_PHY_ID) - printk("Broadcom BCM5461 Copper "); - else if (((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) && - !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) { - printk("Broadcom BCM5701 Integrated Copper "); - } - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) { - printk("Broadcom BCM5703 Integrated "); - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - printk("SerDes "); - else - printk("Copper "); - } - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID) { - printk("Broadcom BCM5704 Integrated "); - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - printk("SerDes "); - else - printk("Copper "); - } - else if (pDevice->PhyFlags & PHY_IS_FIBER){ - if(( pDevice->PhyId & PHY_ID_MASK ) == PHY_BCM5780_PHY_ID) - printk("Broadcom BCM5780S Integrated Serdes "); - - } - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5705_PHY_ID) - printk("Broadcom BCM5705 Integrated Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5750_PHY_ID) - printk("Broadcom BCM5750 Integrated Copper "); - - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5714_PHY_ID) - printk("Broadcom BCM5714 Integrated Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5780_PHY_ID) - printk("Broadcom BCM5780 Integrated Copper "); - - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5752_PHY_ID) - printk("Broadcom BCM5752 Integrated Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID) - printk("Broadcom BCM8002 SerDes "); - else if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) { - printk("Broadcom BCM5703 Integrated SerDes "); - } - else if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) { - printk("Broadcom BCM5704 Integrated SerDes "); - } - else { - printk("Agilent HDMP-1636 SerDes "); - } - } - else { - printk("Unknown "); - } - printk("transceiver found\n"); - -#if (LINUX_VERSION_CODE >= 0x20400) - if (scatter_gather[board_idx]) { - dev->features |= NETIF_F_SG; - if (pUmDevice->using_dac && !(pDevice->Flags & BCM5788_FLAG)) - dev->features |= NETIF_F_HIGHDMA; - } - if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) && - tx_checksum[board_idx]) { - - dev->features |= get_csum_flag( pDevice->ChipRevId); - } -#ifdef BCM_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif -#ifdef BCM_TSO - /* On 5714/15/80 chips, Jumbo Frames and TSO cannot both be enabled at - the same time. Since only one of these features can be enable at a - time, we'll enable only Jumbo Frames and disable TSO when the user - tries to enable both. - */ - dev->features &= ~NETIF_F_TSO; - - if ((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION) && - (enable_tso[board_idx])) { - if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) && - (dev->mtu > 1500)) { - printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name); - } else { - dev->features |= NETIF_F_TSO; - } - } -#endif - printk(KERN_INFO "%s: Scatter-gather %s, 64-bit DMA %s, Tx Checksum %s, ", - dev->name, - (char *) ((dev->features & NETIF_F_SG) ? "ON" : "OFF"), - (char *) ((dev->features & NETIF_F_HIGHDMA) ? "ON" : "OFF"), - (char *) ((dev->features & get_csum_flag( pDevice->ChipRevId)) ? "ON" : "OFF")); -#endif - if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && - rx_checksum[board_idx]) - printk("Rx Checksum ON"); - else - printk("Rx Checksum OFF"); -#ifdef BCM_VLAN - printk(", 802.1Q VLAN ON"); -#endif -#ifdef BCM_TSO - if (dev->features & NETIF_F_TSO) { - printk(", TSO ON"); - } - else -#endif -#ifdef BCM_NAPI_RXPOLL - printk(", NAPI ON"); -#endif - printk("\n"); - -#ifdef BCM_PROC_FS - bcm5700_proc_create_dev(dev); -#endif - register_reboot_notifier(&bcm5700_reboot_notifier); -#ifdef BCM_TASKLET - tasklet_init(&pUmDevice->tasklet, bcm5700_tasklet, - (unsigned long) pUmDevice); -#endif - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) { - if ((REG_RD(pDevice, PciCfg.DualMacCtrl) & - T3_DUAL_MAC_CH_CTRL_MASK) == 3) { - -printk(KERN_WARNING "%s: Device is configured for Hardware Based Teaming which is not supported with this operating system. Please consult the user diagnostic guide to disable Turbo Teaming.\n", dev->name); - } - } - -#if (LINUX_VERSION_CODE > 0x20605) - - if ((pci_dev = pci_get_device(0x1022, 0x700c, NULL))) -#else - if ((pci_dev = pci_find_device(0x1022, 0x700c, NULL))) -#endif - { - u32 val; - - /* Found AMD 762 North bridge */ - pci_read_config_dword(pci_dev, 0x4c, &val); - if ((val & 0x02) == 0) { - pci_write_config_dword(pci_dev, 0x4c, val | 0x02); - printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm5700_driver); - } - } - -#if (LINUX_VERSION_CODE > 0x20605) - - pci_dev_put(pci_dev); - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - - if ((pci_dev = pci_get_device(0x1066, 0x0017, NULL))) { - bcm_msi_chipset_bug = 1; - } - pci_dev_put(pci_dev); -#endif -#endif - - return 0; -} - - -static void __devexit -bcm5700_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - -#ifdef BCM_PROC_FS - bcm5700_proc_remove_dev(dev); -#endif -#ifdef BCM_IOCTL32 - atomic_dec(&bcm5700_load_count); - if (atomic_read(&bcm5700_load_count) == 0) - unregister_ioctl32_conversion(SIOCNICE); -#endif -#ifdef HNDCTF - ctf_dev_unregister(pUmDevice->cih, dev); -#endif /* HNDCTF */ - unregister_netdev(dev); - - if (pUmDevice->lm_dev.pMappedMemBase) - iounmap(pUmDevice->lm_dev.pMappedMemBase); - - pci_release_regions(pdev); - -#if (LINUX_VERSION_CODE < 0x020600) - kfree(dev); -#else - free_netdev(dev); -#endif - - pci_set_drvdata(pdev, NULL); - -} - -int b57_test_intr(UM_DEVICE_BLOCK *pUmDevice); - -#ifdef BCM_WL_EMULATOR -/* new transmit callback */ -static int bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev); -/* keep track of the 2 gige devices */ -static PLM_DEVICE_BLOCK pDev1; -static PLM_DEVICE_BLOCK pDev2; - -static void -bcm5700emu_open(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - static int instance = 0; - static char *wlemu_if = NULL; - char *wlemu_mode = NULL; - //int wlemu_idx = 0; - static int rx_enable = 0; - static int tx_enable = 0; - - /* which interface is the emulator ? */ - if(instance == 0) { - wlemu_if = nvram_get("wlemu_if"); - /* do we emulate rx, tx or both */ - wlemu_mode = nvram_get("wlemu_mode"); - if(wlemu_mode) { - if (!strcmp(wlemu_mode,"rx")) - { - rx_enable = 1; - } - else if (!strcmp(wlemu_mode,"tx")) - { - - tx_enable = 1; - - } - else if (!strcmp(wlemu_mode,"rx_tx")) - { - - rx_enable = 1; - tx_enable = 1; - } - } - } - - instance++; - - /* The context is used for accessing the OSL for emulating devices */ - pDevice->wlc = NULL; - - /* determines if this device is an emulator */ - pDevice->wl_emulate_rx = 0; - pDevice->wl_emulate_tx = 0; - - if(wlemu_if && !strcmp(dev->name,wlemu_if)) - { - /* create an emulator context. */ - pDevice->wlc = (void *)wlcemu_wlccreate((void *)dev); - B57_INFO(("Using %s for wl emulation \n", dev->name)); - if(rx_enable) - { - B57_INFO(("Enabling wl RX emulation \n")); - pDevice->wl_emulate_rx = 1; - } - /* re-direct transmit callback to emulator */ - if(tx_enable) - { - pDevice->wl_emulate_tx = 1; - dev->hard_start_xmit = bcm5700emu_start_xmit; - B57_INFO(("Enabling wl TX emulation \n")); - } - } - /* for debug access to configured devices only */ - if(instance == 1) - pDev1 = pDevice; - else if (instance == 2) - pDev2 = pDevice; -} - -/* Public API to get current emulation info */ -int bcm5700emu_get_info(char *buf) -{ - int len = 0; - PLM_DEVICE_BLOCK p; - - /* look for an emulating device */ - if(pDev1->wlc) { - p = pDev1; - len += sprintf(buf+len,"emulation device : eth0\n"); - } - else if (pDev2->wlc) { - p = pDev2; - len += sprintf(buf+len,"emulation device : eth1\n"); - } - else { - len += sprintf(buf+len,"emulation not activated\n"); - return len; - } - if(p->wl_emulate_rx) - len += sprintf(buf+len,"RX emulation enabled\n"); - else - len += sprintf(buf+len,"RX emulation disabled\n"); - if(p->wl_emulate_tx) - len += sprintf(buf+len,"TX emulation enabled\n"); - else - len += sprintf(buf+len,"TX emulation disabled\n"); - return len; - -} - - -/* Public API to access the bcm5700_start_xmit callback */ - -int -bcm5700emu_forward_xmit(struct sk_buff *skb, struct net_device *dev) -{ - return bcm5700_start_xmit(skb, dev); -} - - -/* hook to kernel txmit callback */ -STATIC int -bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - return wlcemu_start_xmit(skb,pDevice->wlc); -} - -#endif /* BCM_WL_EMULATOR */ - -int -bcm5700_open(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - int rc; - - if (pUmDevice->suspended){ - return -EAGAIN; - } - -#ifdef BCM_WL_EMULATOR - bcm5700emu_open(dev); -#endif - - /* delay for 6 seconds */ - pUmDevice->delayed_link_ind = (6 * HZ) / pUmDevice->timer_interval; - -#ifdef BCM_INT_COAL -#ifndef BCM_NAPI_RXPOLL - pUmDevice->adaptive_expiry = HZ / pUmDevice->timer_interval; -#endif -#endif - -#ifdef INCLUDE_TBI_SUPPORT - if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) && - (pDevice->TbiFlags & TBI_POLLING_FLAGS)) { - pUmDevice->poll_tbi_interval = HZ / pUmDevice->timer_interval; - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) { - pUmDevice->poll_tbi_interval /= 4; - } - pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval; - } -#endif - /* set this timer for 2 seconds */ - pUmDevice->asf_heartbeat = (2 * HZ) / pUmDevice->timer_interval; - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - - - if ( ( (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ) && - (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5714_A0 ) && - (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_AX ) && - (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_BX ) ) && - !bcm_msi_chipset_bug ){ - - if (disable_msi[pUmDevice->index]==1){ - /* do nothing-it's not turned on */ - }else{ - pDevice->Flags |= USING_MSI_FLAG; - - REG_WR(pDevice, Msi.Mode, 2 ); - - rc = pci_enable_msi(pUmDevice->pdev); - - if(rc!=0){ - pDevice->Flags &= ~ USING_MSI_FLAG; - REG_WR(pDevice, Msi.Mode, 1 ); - } - } - } - - -#endif - - if ((rc= request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt, IRQF_SHARED, dev->name, dev))) - { - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - - if(pDevice->Flags & USING_MSI_FLAG) { - - pci_disable_msi(pUmDevice->pdev); - pDevice->Flags &= ~USING_MSI_FLAG; - REG_WR(pDevice, Msi.Mode, 1 ); - - } -#endif - return rc; - } - - pUmDevice->opened = 1; - if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) { - pUmDevice->opened = 0; - free_irq(dev->irq, dev); - bcm5700_freemem(dev); - return -EAGAIN; - } - - bcm5700_set_vlan_mode(pUmDevice); - bcm5700_init_counters(pUmDevice); - - if (pDevice->Flags & UNDI_FIX_FLAG) { - printk(KERN_INFO "%s: Using indirect register access\n", dev->name); - } - - if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) - { - /* Do not use invalid eth addrs: any multicast & all zeros */ - if( is_valid_ether_addr(dev->dev_addr) ){ - LM_SetMacAddress(pDevice, dev->dev_addr); - } - else - { - printk(KERN_INFO "%s: Invalid administered node address\n",dev->name); - memcpy(dev->dev_addr, pDevice->NodeAddress, 6); - } - } - - if (tigon3_debug > 1) - printk(KERN_DEBUG "%s: tigon3_open() irq %d.\n", dev->name, dev->irq); - - QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container, - MAX_RX_PACKET_DESC_COUNT); - - -#if (LINUX_VERSION_CODE < 0x020300) - MOD_INC_USE_COUNT; -#endif - - atomic_set(&pUmDevice->intr_sem, 0); - - LM_EnableInterrupt(pDevice); - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - - if (pDevice->Flags & USING_MSI_FLAG){ - - /* int test to check support on older machines */ - if (b57_test_intr(pUmDevice) != 1) { - - LM_DisableInterrupt(pDevice); - free_irq(pUmDevice->pdev->irq, dev); - pci_disable_msi(pUmDevice->pdev); - REG_WR(pDevice, Msi.Mode, 1 ); - pDevice->Flags &= ~USING_MSI_FLAG; - - rc = LM_ResetAdapter(pDevice); -printk(KERN_ALERT " The MSI support in this system is not functional.\n"); - - if (rc == LM_STATUS_SUCCESS) - rc = 0; - else - rc = -ENODEV; - - if(rc == 0){ - rc = request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt, - SA_SHIRQ, dev->name, dev); - } - - if(rc){ - LM_Halt(pDevice); - bcm5700_freemem(dev); - pUmDevice->opened = 0; - return rc; - } - - - pDevice->InitDone = TRUE; - atomic_set(&pUmDevice->intr_sem, 0); - LM_EnableInterrupt(pDevice); - } - } -#endif - - init_timer(&pUmDevice->timer); - pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval); - pUmDevice->timer.data = (unsigned long)dev; - pUmDevice->timer.function = &bcm5700_timer; - add_timer(&pUmDevice->timer); - - if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) { - init_timer(&pUmDevice->statstimer); - pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval); - pUmDevice->statstimer.data = (unsigned long)dev; - pUmDevice->statstimer.function = &bcm5700_stats_timer; - add_timer(&pUmDevice->statstimer); - } - - if(pDevice->Flags & USING_MSI_FLAG) - printk(KERN_INFO "%s: Using Message Signaled Interrupt (MSI) \n", dev->name); - else - printk(KERN_INFO "%s: Using PCI INTX interrupt \n", dev->name); - - netif_start_queue(dev); - - return 0; -} - - -STATIC void -bcm5700_stats_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - unsigned long flags = 0; - - if (!pUmDevice->opened) - return; - - if (!atomic_read(&pUmDevice->intr_sem) && - !pUmDevice->suspended && - (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) { - BCM5700_LOCK(pUmDevice, flags); - LM_GetStats(pDevice); - BCM5700_UNLOCK(pUmDevice, flags); - } - - pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval); - - add_timer(&pUmDevice->statstimer); -} - - -STATIC void -bcm5700_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - unsigned long flags = 0; - LM_UINT32 value32; - - if (!pUmDevice->opened) - return; - - /* BCM4785: Flush posted writes from GbE to host memory. */ - if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG) - REG_RD(pDevice, HostCoalesce.Mode); - - if (atomic_read(&pUmDevice->intr_sem) || pUmDevice->suspended) { - pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval); - add_timer(&pUmDevice->timer); - return; - } - -#ifdef INCLUDE_TBI_SUPPORT - if ((pDevice->TbiFlags & TBI_POLLING_FLAGS) && - (--pUmDevice->poll_tbi_expiry <= 0)) { - - BCM5700_PHY_LOCK(pUmDevice, flags); - value32 = REG_RD(pDevice, MacCtrl.Status); - if (((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) && - ((value32 & (MAC_STATUS_LINK_STATE_CHANGED | - MAC_STATUS_CFG_CHANGED)) || - !(value32 & MAC_STATUS_PCS_SYNCED))) - || - ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) && - (value32 & (MAC_STATUS_PCS_SYNCED | - MAC_STATUS_SIGNAL_DETECTED)))) - { - LM_SetupPhy(pDevice); - } - BCM5700_PHY_UNLOCK(pUmDevice, flags); - pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval; - - } -#endif - - if (pUmDevice->delayed_link_ind > 0) { - if (pUmDevice->delayed_link_ind == 1) - MM_IndicateStatus(pDevice, pDevice->LinkStatus); - else - pUmDevice->delayed_link_ind--; - } - - if (pUmDevice->crc_counter_expiry > 0) - pUmDevice->crc_counter_expiry--; - - if (!pUmDevice->interrupt) { - if (!(pDevice->Flags & USE_TAGGED_STATUS_FLAG)) { - BCM5700_LOCK(pUmDevice, flags); - if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { - /* This will generate an interrupt */ - REG_WR(pDevice, Grc.LocalCtrl, - pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_SET_INT); - } - else { - REG_WR(pDevice, HostCoalesce.Mode, - pDevice->CoalesceMode | - HOST_COALESCE_ENABLE | - HOST_COALESCE_NOW); - } - if (!(REG_RD(pDevice, DmaWrite.Mode) & - DMA_WRITE_MODE_ENABLE)) { - BCM5700_UNLOCK(pUmDevice, flags); - bcm5700_reset(dev); - } - else { - BCM5700_UNLOCK(pUmDevice, flags); - } - if (pUmDevice->tx_queued) { - pUmDevice->tx_queued = 0; - netif_wake_queue(dev); - } - } -#if (LINUX_VERSION_CODE < 0x02032b) - if ((QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) != - pDevice->TxPacketDescCnt) && - ((jiffies - dev->trans_start) > TX_TIMEOUT)) { - - printk(KERN_WARNING "%s: Tx hung\n", dev->name); - bcm5700_reset(dev); - } -#endif - } -#ifdef BCM_INT_COAL -#ifndef BCM_NAPI_RXPOLL - if (pUmDevice->adaptive_coalesce) { - pUmDevice->adaptive_expiry--; - if (pUmDevice->adaptive_expiry == 0) { - pUmDevice->adaptive_expiry = HZ / - pUmDevice->timer_interval; - bcm5700_adapt_coalesce(pUmDevice); - } - } -#endif -#endif - if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) > - (unsigned int) pUmDevice->rx_buf_repl_panic_thresh) { - /* Generate interrupt and let isr allocate buffers */ - REG_WR(pDevice, HostCoalesce.Mode, pDevice->CoalesceMode | - HOST_COALESCE_ENABLE | HOST_COALESCE_NOW); - } - -#ifdef BCM_ASF - if (pDevice->AsfFlags & ASF_ENABLED) { - pUmDevice->asf_heartbeat--; - if (pUmDevice->asf_heartbeat == 0) { - if( (pDevice->Flags & UNDI_FIX_FLAG) || - (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)) { - MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX, - T3_CMD_NICDRV_ALIVE2); - MEM_WR_OFFSET(pDevice, T3_CMD_LENGTH_MAILBOX, - 4); - MEM_WR_OFFSET(pDevice, T3_CMD_DATA_MAILBOX, 5); - } else { - LM_RegWr(pDevice, - (T3_NIC_MBUF_POOL_ADDR + - T3_CMD_MAILBOX), - T3_CMD_NICDRV_ALIVE2, 1); - LM_RegWr(pDevice, - (T3_NIC_MBUF_POOL_ADDR + - T3_CMD_LENGTH_MAILBOX),4,1); - LM_RegWr(pDevice, - (T3_NIC_MBUF_POOL_ADDR + - T3_CMD_DATA_MAILBOX),5,1); - } - - value32 = REG_RD(pDevice, Grc.RxCpuEvent); - REG_WR(pDevice, Grc.RxCpuEvent, value32 | BIT_14); - pUmDevice->asf_heartbeat = (2 * HZ) / - pUmDevice->timer_interval; - } - } -#endif - - if (pDevice->PhyFlags & PHY_IS_FIBER){ - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_5714_FamFiberCheckLink(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - } - - pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval); - add_timer(&pUmDevice->timer); -} - -STATIC int -bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice) -{ -#ifdef BCM_INT_COAL -#ifndef BCM_NAPI_RXPOLL - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - pUmDevice->rx_curr_coalesce_frames = pDevice->RxMaxCoalescedFrames; - pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks; - pUmDevice->tx_curr_coalesce_frames = pDevice->TxMaxCoalescedFrames; - pUmDevice->rx_last_cnt = 0; - pUmDevice->tx_last_cnt = 0; -#endif -#endif - pUmDevice->phy_crc_count = 0; -#if TIGON3_DEBUG - pUmDevice->tx_zc_count = 0; - pUmDevice->tx_chksum_count = 0; - pUmDevice->tx_himem_count = 0; - pUmDevice->rx_good_chksum_count = 0; - pUmDevice->rx_bad_chksum_count = 0; -#endif -#ifdef BCM_TSO - pUmDevice->tso_pkt_count = 0; -#endif - return 0; -} - -#ifdef BCM_INT_COAL -#ifndef BCM_NAPI_RXPOLL -STATIC int -bcm5700_do_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice, - int rx_frames, int rx_ticks, int tx_frames, int rx_frames_intr) -{ - unsigned long flags = 0; - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - if (pUmDevice->do_global_lock) { - if (spin_is_locked(&pUmDevice->global_lock)) - return 0; - spin_lock_irqsave(&pUmDevice->global_lock, flags); - } - pUmDevice->rx_curr_coalesce_frames = rx_frames; - pUmDevice->rx_curr_coalesce_ticks = rx_ticks; - pUmDevice->tx_curr_coalesce_frames = tx_frames; - pUmDevice->rx_curr_coalesce_frames_intr = rx_frames_intr; - REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames, rx_frames); - - REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, rx_ticks); - - REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames, tx_frames); - - REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt, - rx_frames_intr); - - BCM5700_UNLOCK(pUmDevice, flags); - return 0; -} - -STATIC int -bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice) -{ - PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev; - uint rx_curr_cnt, tx_curr_cnt, rx_delta, tx_delta, total_delta; - - rx_curr_cnt = pDevice->pStatsBlkVirt->ifHCInUcastPkts.Low; - tx_curr_cnt = pDevice->pStatsBlkVirt->ifHCOutUcastPkts.Low; - if ((rx_curr_cnt <= pUmDevice->rx_last_cnt) || - (tx_curr_cnt < pUmDevice->tx_last_cnt)) { - - /* skip if there is counter rollover */ - pUmDevice->rx_last_cnt = rx_curr_cnt; - pUmDevice->tx_last_cnt = tx_curr_cnt; - return 0; - } - - rx_delta = rx_curr_cnt - pUmDevice->rx_last_cnt; - tx_delta = tx_curr_cnt - pUmDevice->tx_last_cnt; - total_delta = (((rx_delta + rx_delta) + tx_delta) / 3) << 1; - - pUmDevice->rx_last_cnt = rx_curr_cnt; - pUmDevice->tx_last_cnt = tx_curr_cnt; - - if (total_delta < ADAPTIVE_LO_PKT_THRESH) { - if (pUmDevice->rx_curr_coalesce_frames != - ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES) { - - bcm5700_do_adapt_coalesce(pUmDevice, - ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES, - ADAPTIVE_LO_RX_COALESCING_TICKS, - ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES, - ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES_DURING_INT); - } - } - else if (total_delta < ADAPTIVE_HI_PKT_THRESH) { - if (pUmDevice->rx_curr_coalesce_frames != - DEFAULT_RX_MAX_COALESCED_FRAMES) { - - bcm5700_do_adapt_coalesce(pUmDevice, - DEFAULT_RX_MAX_COALESCED_FRAMES, - DEFAULT_RX_COALESCING_TICKS, - DEFAULT_TX_MAX_COALESCED_FRAMES, - DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT); - } - } - else { - if (pUmDevice->rx_curr_coalesce_frames != - ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES) { - - bcm5700_do_adapt_coalesce(pUmDevice, - ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES, - ADAPTIVE_HI_RX_COALESCING_TICKS, - ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES, - ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT); - } - } - return 0; -} -#endif -#endif - -STATIC void -bcm5700_reset(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - unsigned long flags; - -#ifdef BCM_TSO - - if( (dev->features & NETIF_F_TSO) && - (pUmDevice->tx_full) ) { - - dev->features &= ~NETIF_F_TSO; - } -#endif - - netif_stop_queue(dev); - bcm5700_intr_off(pUmDevice); - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_ResetAdapter(pDevice); - pDevice->InitDone = TRUE; - bcm5700_do_rx_mode(dev); - bcm5700_set_vlan_mode(pUmDevice); - bcm5700_init_counters(pUmDevice); - if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) { - LM_SetMacAddress(pDevice, dev->dev_addr); - } - BCM5700_PHY_UNLOCK(pUmDevice, flags); - atomic_set(&pUmDevice->intr_sem, 1); - bcm5700_intr_on(pUmDevice); - netif_wake_queue(dev); -} - -STATIC void -bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - LM_UINT32 ReceiveMask = pDevice->ReceiveMask; - int vlan_tag_mode = pUmDevice->vlan_tag_mode; - - if (vlan_tag_mode == VLAN_TAG_MODE_AUTO_STRIP) { - if (pDevice->AsfFlags & ASF_ENABLED) { - vlan_tag_mode = VLAN_TAG_MODE_FORCED_STRIP; - } - else { - vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP; - } - } - if (vlan_tag_mode == VLAN_TAG_MODE_NORMAL_STRIP) { - ReceiveMask |= LM_KEEP_VLAN_TAG; -#ifdef BCM_VLAN - if (pUmDevice->vlgrp) - ReceiveMask &= ~LM_KEEP_VLAN_TAG; -#endif -#ifdef NICE_SUPPORT - if (pUmDevice->nice_rx) - ReceiveMask &= ~LM_KEEP_VLAN_TAG; -#endif - } - else if (vlan_tag_mode == VLAN_TAG_MODE_FORCED_STRIP) { - ReceiveMask &= ~LM_KEEP_VLAN_TAG; - } - if (ReceiveMask != pDevice->ReceiveMask) - { - LM_SetReceiveMask(pDevice, ReceiveMask); - } -} - -static void -bcm5700_poll_wait(UM_DEVICE_BLOCK *pUmDevice) -{ -#ifdef BCM_NAPI_RXPOLL - while (pUmDevice->lm_dev.RxPoll) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } -#endif -} - - -#ifdef BCM_VLAN -STATIC void -bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - - bcm5700_intr_off(pUmDevice); - bcm5700_poll_wait(pUmDevice); - pUmDevice->vlgrp = vlgrp; - bcm5700_set_vlan_mode(pUmDevice); - bcm5700_intr_on(pUmDevice); -} - -STATIC void -bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - - bcm5700_intr_off(pUmDevice); - bcm5700_poll_wait(pUmDevice); - if (pUmDevice->vlgrp) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - vlan_group_set_device(pUmDevice->vlgrp, vid, NULL); -#else - pUmDevice->vlgrp->vlan_devices[vid] = NULL; -#endif - } - bcm5700_intr_on(pUmDevice); -} -#endif - -STATIC int -bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - unsigned long flags = 0; - int frag_no; -#ifdef NICE_SUPPORT - vlan_tag_t *vlan_tag; -#endif -#ifdef BCM_TSO - LM_UINT32 mss = 0 ; - uint16_t ip_tcp_len, tcp_opt_len, tcp_seg_flags; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - struct tcphdr *th; - struct iphdr *iph; -#endif - - if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) || - !pDevice->InitDone || pUmDevice->suspended) - { - dev_kfree_skb(skb); - return 0; - } - -#if (LINUX_VERSION_CODE < 0x02032b) - if (test_and_set_bit(0, &dev->tbusy)) { - return 1; - } -#endif - - if (pUmDevice->do_global_lock && pUmDevice->interrupt) { - netif_stop_queue(dev); - pUmDevice->tx_queued = 1; - if (!pUmDevice->interrupt) { - netif_wake_queue(dev); - pUmDevice->tx_queued = 0; - } - return 1; - } - - pPacket = (PLM_PACKET) - QQ_PopHead(&pDevice->TxPacketFreeQ.Container); - if (pPacket == 0) { - netif_stop_queue(dev); - pUmDevice->tx_full = 1; - if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container)) { - netif_wake_queue(dev); - pUmDevice->tx_full = 0; - } - return 1; - } - pUmPacket = (PUM_PACKET) pPacket; - pUmPacket->skbuff = skb; - pUmDevice->stats.tx_bytes += skb->len; - - if (skb->ip_summed == CHECKSUM_HW) { - pPacket->Flags = SND_BD_FLAG_TCP_UDP_CKSUM; -#if TIGON3_DEBUG - pUmDevice->tx_chksum_count++; -#endif - } - else { - pPacket->Flags = 0; - } -#if MAX_SKB_FRAGS - frag_no = skb_shinfo(skb)->nr_frags; -#else - frag_no = 0; -#endif - if (atomic_read(&pDevice->SendBdLeft) < (frag_no + 1)) { - netif_stop_queue(dev); - pUmDevice->tx_full = 1; - QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket); - if (atomic_read(&pDevice->SendBdLeft) >= (frag_no + 1)) { - netif_wake_queue(dev); - pUmDevice->tx_full = 0; - } - return 1; - } - - pPacket->u.Tx.FragCount = frag_no + 1; -#if TIGON3_DEBUG - if (pPacket->u.Tx.FragCount > 1) - pUmDevice->tx_zc_count++; -#endif - -#ifdef BCM_VLAN - if (pUmDevice->vlgrp && vlan_tx_tag_present(skb)) { - pPacket->VlanTag = vlan_tx_tag_get(skb); - pPacket->Flags |= SND_BD_FLAG_VLAN_TAG; - } -#endif -#ifdef NICE_SUPPORT - vlan_tag = (vlan_tag_t *) &skb->cb[0]; - if (vlan_tag->signature == 0x5555) { - pPacket->VlanTag = vlan_tag->tag; - pPacket->Flags |= SND_BD_FLAG_VLAN_TAG; - vlan_tag->signature = 0; - } -#endif - -#ifdef BCM_TSO -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16) - if ((mss = (LM_UINT32) skb_shinfo(skb)->gso_size) && - (skb->len > pDevice->TxMtu)) { -#else - if ((mss = (LM_UINT32) skb_shinfo(skb)->tso_size) && - (skb->len > pDevice->TxMtu)) { -#endif - -#if (LINUX_VERSION_CODE >= 0x02060c) - - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - - dev_kfree_skb(skb); - return 0; - } -#endif - pUmDevice->tso_pkt_count++; - - pPacket->Flags |= SND_BD_FLAG_CPU_PRE_DMA | - SND_BD_FLAG_CPU_POST_DMA; - - tcp_opt_len = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - th = (struct tcphdr *)skb_transport_header(skb); - iph = (struct iphdr *)skb_network_header(skb); - - ASSERT((iph != NULL) && (th != NULL)); - - if (th->doff > 5) { - tcp_opt_len = (th->doff - 5) << 2; - } - ip_tcp_len = (iph->ihl << 2) + sizeof(struct tcphdr); - iph->check = 0; - - if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ){ - th->check = 0; - pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM; - } - else { - th->check = ~csum_tcpudp_magic( - iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - } - - iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - tcp_seg_flags = 0; - - if (tcp_opt_len || (iph->ihl > 5)) { - if ( T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) ){ - tcp_seg_flags = - ((iph->ihl - 5) + - (tcp_opt_len >> 2)) << 11; - } - else { - pPacket->Flags |= - ((iph->ihl - 5) + - (tcp_opt_len >> 2)) << 12; - } - } -#else - if (skb->h.th->doff > 5) { - tcp_opt_len = (skb->h.th->doff - 5) << 2; - } - ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr); - skb->nh.iph->check = 0; - - if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ){ - skb->h.th->check = 0; - pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM; - } - else { - skb->h.th->check = ~csum_tcpudp_magic( - skb->nh.iph->saddr, skb->nh.iph->daddr, - 0, IPPROTO_TCP, 0); - } - - skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - tcp_seg_flags = 0; - - if (tcp_opt_len || (skb->nh.iph->ihl > 5)) { - if ( T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) ){ - tcp_seg_flags = - ((skb->nh.iph->ihl - 5) + - (tcp_opt_len >> 2)) << 11; - } - else { - pPacket->Flags |= - ((skb->nh.iph->ihl - 5) + - (tcp_opt_len >> 2)) << 12; - } - } -#endif - pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags; - } - else - { - pPacket->u.Tx.MaxSegmentSize = 0; - } -#endif - BCM5700_LOCK(pUmDevice, flags); - LM_SendPacket(pDevice, pPacket); - BCM5700_UNLOCK(pUmDevice, flags); - -#if (LINUX_VERSION_CODE < 0x02032b) - netif_wake_queue(dev); -#endif - dev->trans_start = jiffies; - - - return 0; -} - -#ifdef BCM_NAPI_RXPOLL -STATIC int -bcm5700_poll(struct net_device *dev, int *budget) -{ - int orig_budget = *budget; - int work_done; - UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) dev->priv; - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - unsigned long flags = 0; - LM_UINT32 tag; - - if (orig_budget > dev->quota) - orig_budget = dev->quota; - - BCM5700_LOCK(pUmDevice, flags); - /* BCM4785: Flush posted writes from GbE to host memory. */ - if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG) - REG_RD(pDevice, HostCoalesce.Mode); - work_done = LM_ServiceRxPoll(pDevice, orig_budget); - *budget -= work_done; - dev->quota -= work_done; - - if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) { - replenish_rx_buffers(pUmDevice, 0); - } - BCM5700_UNLOCK(pUmDevice, flags); - if (work_done) { - MM_IndicateRxPackets(pDevice); - BCM5700_LOCK(pUmDevice, flags); - LM_QueueRxPackets(pDevice); - BCM5700_UNLOCK(pUmDevice, flags); - } - if ((work_done < orig_budget) || atomic_read(&pUmDevice->intr_sem) || - pUmDevice->suspended) { - - netif_rx_complete(dev); - BCM5700_LOCK(pUmDevice, flags); - REG_WR(pDevice, Grc.Mode, pDevice->GrcMode); - pDevice->RxPoll = FALSE; - if (pDevice->RxPoll) { - BCM5700_UNLOCK(pUmDevice, flags); - return 0; - } - /* Take care of possible missed rx interrupts */ - REG_RD_BACK(pDevice, Grc.Mode); /* flush the register write */ - tag = pDevice->pStatusBlkVirt->StatusTag; - if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) || - (pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx != - pDevice->RcvRetConIdx)) { - - REG_WR(pDevice, HostCoalesce.Mode, - pDevice->CoalesceMode | HOST_COALESCE_ENABLE | - HOST_COALESCE_NOW); - } - /* If a new status block is pending in the WDMA state machine */ - /* before the register write to enable the rx interrupt, */ - /* the new status block may DMA with no interrupt. In this */ - /* scenario, the tag read above will be older than the tag in */ - /* the pending status block and writing the older tag will */ - /* cause interrupt to be generated. */ - else if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) { - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, - tag << 24); - /* Make sure we service tx in case some tx interrupts */ - /* are cleared */ - if (atomic_read(&pDevice->SendBdLeft) < - (T3_SEND_RCB_ENTRY_COUNT / 2)) { - REG_WR(pDevice, HostCoalesce.Mode, - pDevice->CoalesceMode | - HOST_COALESCE_ENABLE | - HOST_COALESCE_NOW); - } - } - BCM5700_UNLOCK(pUmDevice, flags); - return 0; - } - return 1; -} -#endif /* BCM_NAPI_RXPOLL */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -STATIC irqreturn_t -bcm5700_interrupt(int irq, void *dev_instance) -#else -STATIC irqreturn_t -bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#endif -{ - struct net_device *dev = (struct net_device *)dev_instance; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - LM_UINT32 oldtag, newtag; - int i, max_intr_loop; -#ifdef BCM_TASKLET - int repl_buf_count; -#endif - unsigned int handled = 1; - - if (!pDevice->InitDone) { - handled = 0; - return IRQ_RETVAL(handled); - } - - bcm5700_intr_lock(pUmDevice); - if (atomic_read(&pUmDevice->intr_sem)) { - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); - bcm5700_intr_unlock(pUmDevice); - handled = 0; - return IRQ_RETVAL(handled); - } - - if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) { - printk(KERN_ERR "%s: Duplicate entry of the interrupt handler\n", - dev->name); - bcm5700_intr_unlock(pUmDevice); - handled = 0; - return IRQ_RETVAL(handled); - } - - /* BCM4785: Flush posted writes from GbE to host memory. */ - if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG) - REG_RD(pDevice, HostCoalesce.Mode); - - if ((pDevice->Flags & USING_MSI_FLAG) || - (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) || - !(REG_RD(pDevice,PciCfg.PciState) & T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) ) - { - - if (pUmDevice->intr_test) { - if (!(REG_RD(pDevice, PciCfg.PciState) & - T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) || - pDevice->Flags & USING_MSI_FLAG ) { - pUmDevice->intr_test_result = 1; - } - pUmDevice->intr_test = 0; - } - -#ifdef BCM_NAPI_RXPOLL - max_intr_loop = 1; -#else - max_intr_loop = 50; -#endif - if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) { - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); - oldtag = pDevice->pStatusBlkVirt->StatusTag; - - for (i = 0; ; i++) { - pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED; - - LM_ServiceInterrupts(pDevice); - /* BCM4785: Flush GbE posted writes to host memory. */ - if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG) - MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low); - newtag = pDevice->pStatusBlkVirt->StatusTag; - if ((newtag == oldtag) || (i > max_intr_loop)) { - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, oldtag << 24); - pDevice->LastTag = oldtag; - if (pDevice->Flags & UNDI_FIX_FLAG) { - REG_WR(pDevice, Grc.LocalCtrl, - pDevice->GrcLocalCtrl | 0x2); - } - break; - } - oldtag = newtag; - } - } - else - { - i = 0; - do { - uint dummy; - - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); - pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED; - LM_ServiceInterrupts(pDevice); - MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0); - dummy = MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low); - i++; - } - while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) && - (i < max_intr_loop)); - - if (pDevice->Flags & UNDI_FIX_FLAG) { - REG_WR(pDevice, Grc.LocalCtrl, - pDevice->GrcLocalCtrl | 0x2); - } - } - } - else - { - /* not my interrupt */ - handled = 0; - } - -#ifdef BCM_TASKLET - repl_buf_count = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container); - if (((repl_buf_count > pUmDevice->rx_buf_repl_panic_thresh) || - pDevice->QueueAgain) && - (!test_and_set_bit(0, &pUmDevice->tasklet_busy))) { - - replenish_rx_buffers(pUmDevice, pUmDevice->rx_buf_repl_isr_limit); - clear_bit(0, (void*)&pUmDevice->tasklet_busy); - } - else if ((repl_buf_count > pUmDevice->rx_buf_repl_thresh) && - !pUmDevice->tasklet_pending) { - - pUmDevice->tasklet_pending = 1; - tasklet_schedule(&pUmDevice->tasklet); - } -#else -#ifdef BCM_NAPI_RXPOLL - if (!pDevice->RxPoll && - QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) { - pDevice->RxPoll = 1; - MM_ScheduleRxPoll(pDevice); - } -#else - if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) { - replenish_rx_buffers(pUmDevice, 0); - } - - if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) || - pDevice->QueueAgain) { - - LM_QueueRxPackets(pDevice); - } -#endif -#endif - - clear_bit(0, (void*)&pUmDevice->interrupt); - bcm5700_intr_unlock(pUmDevice); - if (pUmDevice->tx_queued) { - pUmDevice->tx_queued = 0; - netif_wake_queue(dev); - } - return IRQ_RETVAL(handled); -} - - -#ifdef BCM_TASKLET -STATIC void -bcm5700_tasklet(unsigned long data) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data; - unsigned long flags = 0; - - /* RH 7.2 Beta 3 tasklets are reentrant */ - if (test_and_set_bit(0, &pUmDevice->tasklet_busy)) { - pUmDevice->tasklet_pending = 0; - return; - } - - pUmDevice->tasklet_pending = 0; - if (pUmDevice->opened && !pUmDevice->suspended) { - BCM5700_LOCK(pUmDevice, flags); - replenish_rx_buffers(pUmDevice, 0); - BCM5700_UNLOCK(pUmDevice, flags); - } - - clear_bit(0, &pUmDevice->tasklet_busy); -} -#endif - -STATIC int -bcm5700_close(struct net_device *dev) -{ - - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - -#if (LINUX_VERSION_CODE < 0x02032b) - dev->start = 0; -#endif - netif_stop_queue(dev); - pUmDevice->opened = 0; - -#ifdef BCM_ASF - if( !(pDevice->AsfFlags & ASF_ENABLED) ) -#endif -#ifdef BCM_WOL - if( enable_wol[pUmDevice->index] == 0 ) -#endif - B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name)); - - if (tigon3_debug > 1) - printk(KERN_DEBUG "%s: Shutting down Tigon3\n", - dev->name); - - LM_MulticastClear(pDevice); - bcm5700_shutdown(pUmDevice); - - if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) { - del_timer_sync(&pUmDevice->statstimer); - } - - del_timer_sync(&pUmDevice->timer); - - free_irq(pUmDevice->pdev->irq, dev); - -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - - if(pDevice->Flags & USING_MSI_FLAG) { - pci_disable_msi(pUmDevice->pdev); - REG_WR(pDevice, Msi.Mode, 1 ); - pDevice->Flags &= ~USING_MSI_FLAG; - } - -#endif - - -#if (LINUX_VERSION_CODE < 0x020300) - MOD_DEC_USE_COUNT; -#endif - { - /* BCM4785: Don't go to low-power state because it will power down the smbus block. */ - if (!(pDevice->Flags & SB_CORE_FLAG)) - LM_SetPowerState(pDevice, LM_POWER_STATE_D3); - } - - bcm5700_freemem(dev); - - QQ_InitQueue(&pDevice->RxPacketFreeQ.Container, - MAX_RX_PACKET_DESC_COUNT); - - return 0; -} - -STATIC int -bcm5700_freemem(struct net_device *dev) -{ - int i; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - for (i = 0; i < pUmDevice->mem_list_num; i++) { - if (pUmDevice->mem_size_list[i] == 0) { - kfree(pUmDevice->mem_list[i]); - } - else { - pci_free_consistent(pUmDevice->pdev, - (size_t) pUmDevice->mem_size_list[i], - pUmDevice->mem_list[i], - pUmDevice->dma_list[i]); - } - } - - pDevice->pStatusBlkVirt = 0; - pDevice->pStatsBlkVirt = 0; - pUmDevice->mem_list_num = 0; - -#ifdef NICE_SUPPORT - if (!pUmDevice->opened) { - for (i = 0; i < MAX_MEM2; i++) { - if (pUmDevice->mem_size_list2[i]) { - bcm5700_freemem2(pUmDevice, i); - } - } - } -#endif - return 0; -} - -#ifdef NICE_SUPPORT -/* Frees consistent memory allocated through ioctl */ -/* The memory to be freed is in mem_list2[index] */ -STATIC int -bcm5700_freemem2(UM_DEVICE_BLOCK *pUmDevice, int index) -{ -#if (LINUX_VERSION_CODE >= 0x020400) - void *ptr; - struct page *pg, *last_pg; - - /* Probably won't work on some architectures */ - ptr = pUmDevice->mem_list2[index], - pg = virt_to_page(ptr); - last_pg = virt_to_page(ptr + pUmDevice->mem_size_list2[index] - 1); - for (; ; pg++) { -#if (LINUX_VERSION_CODE > 0x020500) - ClearPageReserved(pg); -#else - mem_map_unreserve(pg); -#endif - if (pg == last_pg) - break; - } - pci_free_consistent(pUmDevice->pdev, - (size_t) pUmDevice->mem_size_list2[index], - pUmDevice->mem_list2[index], - pUmDevice->dma_list2[index]); - pUmDevice->mem_size_list2[index] = 0; -#endif - return 0; -} -#endif - -uint64_t -bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice) -{ - PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev; - LM_UINT32 Value32; - PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt; - unsigned long flags; - - if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) && - !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) { - - if (!pUmDevice->opened || !pDevice->InitDone) - { - - return 0; - } - - /* regulate MDIO access during run time */ - if (pUmDevice->crc_counter_expiry > 0) - return pUmDevice->phy_crc_count; - - pUmDevice->crc_counter_expiry = (5 * HZ) / - pUmDevice->timer_interval; - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_ReadPhy(pDevice, 0x1e, &Value32); - if ((Value32 & 0x8000) == 0) - LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000); - LM_ReadPhy(pDevice, 0x14, &Value32); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - /* Sometimes data on the MDIO bus can be corrupted */ - if (Value32 != 0xffff) - pUmDevice->phy_crc_count += Value32; - return pUmDevice->phy_crc_count; - } - else if (pStats == 0) { - return 0; - } - else { - return (MM_GETSTATS64(pStats->dot3StatsFCSErrors)); - } -} - -uint64_t -bcm5700_rx_err_count(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - T3_STATS_BLOCK *pStats = (T3_STATS_BLOCK *) pDevice->pStatsBlkVirt; - - if (pStats == 0) - return 0; - return (bcm5700_crc_count(pUmDevice) + - MM_GETSTATS64(pStats->dot3StatsAlignmentErrors) + - MM_GETSTATS64(pStats->etherStatsUndersizePkts) + - MM_GETSTATS64(pStats->etherStatsFragments) + - MM_GETSTATS64(pStats->dot3StatsFramesTooLong) + - MM_GETSTATS64(pStats->etherStatsJabbers)); -} - -STATIC struct net_device_stats * -bcm5700_get_stats(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt; - struct net_device_stats *p_netstats = &pUmDevice->stats; - - if (pStats == 0) - return p_netstats; - - /* Get stats from LM */ - p_netstats->rx_packets = - MM_GETSTATS(pStats->ifHCInUcastPkts) + - MM_GETSTATS(pStats->ifHCInMulticastPkts) + - MM_GETSTATS(pStats->ifHCInBroadcastPkts); - p_netstats->tx_packets = - MM_GETSTATS(pStats->ifHCOutUcastPkts) + - MM_GETSTATS(pStats->ifHCOutMulticastPkts) + - MM_GETSTATS(pStats->ifHCOutBroadcastPkts); - /* There counters seem to be innacurate. Use byte number accumulation - instead. - p_netstats->rx_bytes = MM_GETSTATS(pStats->ifHCInOctets); - p_netstats->tx_bytes = MM_GETSTATS(pStats->ifHCOutOctets); - */ - p_netstats->tx_errors = - MM_GETSTATS(pStats->dot3StatsInternalMacTransmitErrors) + - MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors) + - MM_GETSTATS(pStats->ifOutDiscards) + - MM_GETSTATS(pStats->ifOutErrors); - p_netstats->multicast = MM_GETSTATS(pStats->ifHCInMulticastPkts); - p_netstats->collisions = MM_GETSTATS(pStats->etherStatsCollisions); - p_netstats->rx_length_errors = - MM_GETSTATS(pStats->dot3StatsFramesTooLong) + - MM_GETSTATS(pStats->etherStatsUndersizePkts); - p_netstats->rx_over_errors = MM_GETSTATS(pStats->nicNoMoreRxBDs); - p_netstats->rx_frame_errors = - MM_GETSTATS(pStats->dot3StatsAlignmentErrors); - p_netstats->rx_crc_errors = (unsigned long) - bcm5700_crc_count(pUmDevice); - p_netstats->rx_errors = (unsigned long) - bcm5700_rx_err_count(pUmDevice); - - p_netstats->tx_aborted_errors = MM_GETSTATS(pStats->ifOutDiscards); - p_netstats->tx_carrier_errors = - MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors); - - return p_netstats; -} - -void -b57_suspend_chip(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - if (pUmDevice->opened) { - bcm5700_intr_off(pUmDevice); - netif_carrier_off(pUmDevice->dev); - netif_stop_queue(pUmDevice->dev); -#ifdef BCM_TASKLET - tasklet_kill(&pUmDevice->tasklet); -#endif - bcm5700_poll_wait(pUmDevice); - } - pUmDevice->suspended = 1; - LM_ShutdownChip(pDevice, LM_SUSPEND_RESET); -} - -void -b57_resume_chip(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - if (pUmDevice->suspended) { - pUmDevice->suspended = 0; - if (pUmDevice->opened) { - bcm5700_reset(pUmDevice->dev); - } - else { - LM_ShutdownChip(pDevice, LM_SHUTDOWN_RESET); - } - } -} - -/* Returns 0 on failure, 1 on success */ -int -b57_test_intr(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - int j; - - if (!pUmDevice->opened) - return 0; - pUmDevice->intr_test_result = 0; - pUmDevice->intr_test = 1; - - REG_WR(pDevice, HostCoalesce.Mode, - pDevice->CoalesceMode | HOST_COALESCE_ENABLE | - HOST_COALESCE_NOW); - - for (j = 0; j < 10; j++) { - if (pUmDevice->intr_test_result){ - break; - } - - REG_WR(pDevice, HostCoalesce.Mode, - pDevice->CoalesceMode | HOST_COALESCE_ENABLE | - HOST_COALESCE_NOW); - - MM_Sleep(pDevice, 1); - } - - return pUmDevice->intr_test_result; - -} - -#ifdef SIOCETHTOOL - -#ifdef ETHTOOL_GSTRINGS - -#define ETH_NUM_STATS 30 -#define RX_CRC_IDX 5 -#define RX_MAC_ERR_IDX 14 - -struct { - char string[ETH_GSTRING_LEN]; -} bcm5700_stats_str_arr[ETH_NUM_STATS] = { - { "rx_unicast_packets" }, - { "rx_multicast_packets" }, - { "rx_broadcast_packets" }, - { "rx_bytes" }, - { "rx_fragments" }, - { "rx_crc_errors" }, /* this needs to be calculated */ - { "rx_align_errors" }, - { "rx_xon_frames" }, - { "rx_xoff_frames" }, - { "rx_long_frames" }, - { "rx_short_frames" }, - { "rx_jabber" }, - { "rx_discards" }, - { "rx_errors" }, - { "rx_mac_errors" }, /* this needs to be calculated */ - { "tx_unicast_packets" }, - { "tx_multicast_packets" }, - { "tx_broadcast_packets" }, - { "tx_bytes" }, - { "tx_deferred" }, - { "tx_single_collisions" }, - { "tx_multi_collisions" }, - { "tx_total_collisions" }, - { "tx_excess_collisions" }, - { "tx_late_collisions" }, - { "tx_xon_frames" }, - { "tx_xoff_frames" }, - { "tx_internal_mac_errors" }, - { "tx_carrier_errors" }, - { "tx_errors" }, -}; - -#define STATS_OFFSET(offset_name) ((OFFSETOF(T3_STATS_BLOCK, offset_name)) / sizeof(uint64_t)) - -#ifdef __BIG_ENDIAN -#define SWAP_DWORD_64(x) (x) -#else -#define SWAP_DWORD_64(x) ((x << 32) | (x >> 32)) -#endif - -unsigned long bcm5700_stats_offset_arr[ETH_NUM_STATS] = { - STATS_OFFSET(ifHCInUcastPkts), - STATS_OFFSET(ifHCInMulticastPkts), - STATS_OFFSET(ifHCInBroadcastPkts), - STATS_OFFSET(ifHCInOctets), - STATS_OFFSET(etherStatsFragments), - 0, - STATS_OFFSET(dot3StatsAlignmentErrors), - STATS_OFFSET(xonPauseFramesReceived), - STATS_OFFSET(xoffPauseFramesReceived), - STATS_OFFSET(dot3StatsFramesTooLong), - STATS_OFFSET(etherStatsUndersizePkts), - STATS_OFFSET(etherStatsJabbers), - STATS_OFFSET(ifInDiscards), - STATS_OFFSET(ifInErrors), - 0, - STATS_OFFSET(ifHCOutUcastPkts), - STATS_OFFSET(ifHCOutMulticastPkts), - STATS_OFFSET(ifHCOutBroadcastPkts), - STATS_OFFSET(ifHCOutOctets), - STATS_OFFSET(dot3StatsDeferredTransmissions), - STATS_OFFSET(dot3StatsSingleCollisionFrames), - STATS_OFFSET(dot3StatsMultipleCollisionFrames), - STATS_OFFSET(etherStatsCollisions), - STATS_OFFSET(dot3StatsExcessiveCollisions), - STATS_OFFSET(dot3StatsLateCollisions), - STATS_OFFSET(outXonSent), - STATS_OFFSET(outXoffSent), - STATS_OFFSET(dot3StatsInternalMacTransmitErrors), - STATS_OFFSET(dot3StatsCarrierSenseErrors), - STATS_OFFSET(ifOutErrors), -}; - -#endif /* ETHTOOL_GSTRINGS */ - -#ifdef ETHTOOL_TEST -#define ETH_NUM_TESTS 6 -struct { - char string[ETH_GSTRING_LEN]; -} bcm5700_tests_str_arr[ETH_NUM_TESTS] = { - { "register test (offline)" }, - { "memory test (offline)" }, - { "loopback test (offline)" }, - { "nvram test (online)" }, - { "interrupt test (online)" }, - { "link test (online)" }, -}; - -extern LM_STATUS b57_test_registers(UM_DEVICE_BLOCK *pUmDevice); -extern LM_STATUS b57_test_memory(UM_DEVICE_BLOCK *pUmDevice); -extern LM_STATUS b57_test_nvram(UM_DEVICE_BLOCK *pUmDevice); -extern LM_STATUS b57_test_link(UM_DEVICE_BLOCK *pUmDevice); -extern LM_STATUS b57_test_loopback(UM_DEVICE_BLOCK *pUmDevice, int looptype, int linespeed); -#endif - -#ifdef ETHTOOL_GREGS -#if (LINUX_VERSION_CODE >= 0x02040f) -static void -bcm5700_get_reg_blk(UM_DEVICE_BLOCK *pUmDevice, u32 **buf, u32 start, u32 end, - int reserved) -{ - u32 offset; - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - - if (reserved) { - memset(*buf, 0, end - start); - *buf = *buf + (end - start)/4; - return; - } - for (offset = start; offset < end; offset+=4, *buf = *buf + 1) { - if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){ - if (((offset >= 0x3400) && (offset < 0x3c00)) || - ((offset >= 0x5400) && (offset < 0x5800)) || - ((offset >= 0x6400) && (offset < 0x6800))) { - **buf = 0; - continue; - } - } - **buf = REG_RD_OFFSET(pDevice, offset); - } -} -#endif -#endif - -static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd ethcmd; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - - if (mm_copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd.cmd) { -#ifdef ETHTOOL_GDRVINFO - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - - strcpy(info.driver, bcm5700_driver); -#ifdef INCLUDE_5701_AX_FIX - if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0) { - extern int t3FwReleaseMajor; - extern int t3FwReleaseMinor; - extern int t3FwReleaseFix; - - sprintf(info.fw_version, "%i.%i.%i", - t3FwReleaseMajor, t3FwReleaseMinor, - t3FwReleaseFix); - } -#endif - strcpy(info.fw_version, pDevice->BootCodeVer); - strcpy(info.version, bcm5700_version); -#if (LINUX_VERSION_CODE <= 0x020422) - strcpy(info.bus_info, pUmDevice->pdev->slot_name); -#else - strcpy(info.bus_info, pci_name(pUmDevice->pdev)); -#endif - - - -#ifdef ETHTOOL_GEEPROM - BCM_EEDUMP_LEN(&info, pDevice->NvramSize); -#endif -#ifdef ETHTOOL_GREGS - /* dump everything, including holes in the register space */ - info.regdump_len = 0x6c00; -#endif -#ifdef ETHTOOL_GSTATS - info.n_stats = ETH_NUM_STATS; -#endif -#ifdef ETHTOOL_TEST - info.testinfo_len = ETH_NUM_TESTS; -#endif - if (mm_copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } -#endif - case ETHTOOL_GSET: { - if ((pDevice->TbiFlags & ENABLE_TBI_FLAG)|| - (pDevice->PhyFlags & PHY_IS_FIBER)) { - ethcmd.supported = - (SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg); - ethcmd.supported |= SUPPORTED_FIBRE; - ethcmd.port = PORT_FIBRE; - } else { - ethcmd.supported = - (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg); - ethcmd.supported |= SUPPORTED_TP; - ethcmd.port = PORT_TP; - } - - ethcmd.transceiver = XCVR_INTERNAL; - ethcmd.phy_address = 0; - - if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) - ethcmd.speed = SPEED_1000; - else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) - ethcmd.speed = SPEED_100; - else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) - ethcmd.speed = SPEED_10; - else - ethcmd.speed = 0; - - if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) - ethcmd.duplex = DUPLEX_FULL; - else - ethcmd.duplex = DUPLEX_HALF; - - if (pDevice->DisableAutoNeg == FALSE) { - ethcmd.autoneg = AUTONEG_ENABLE; - ethcmd.advertising = ADVERTISED_Autoneg; - if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) || - (pDevice->PhyFlags & PHY_IS_FIBER)) { - ethcmd.advertising |= - ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE; - } - else { - ethcmd.advertising |= - ADVERTISED_TP; - if (pDevice->advertising & - PHY_AN_AD_10BASET_HALF) { - - ethcmd.advertising |= - ADVERTISED_10baseT_Half; - } - if (pDevice->advertising & - PHY_AN_AD_10BASET_FULL) { - - ethcmd.advertising |= - ADVERTISED_10baseT_Full; - } - if (pDevice->advertising & - PHY_AN_AD_100BASETX_HALF) { - - ethcmd.advertising |= - ADVERTISED_100baseT_Half; - } - if (pDevice->advertising & - PHY_AN_AD_100BASETX_FULL) { - - ethcmd.advertising |= - ADVERTISED_100baseT_Full; - } - if (pDevice->advertising1000 & - BCM540X_AN_AD_1000BASET_HALF) { - - ethcmd.advertising |= - ADVERTISED_1000baseT_Half; - } - if (pDevice->advertising1000 & - BCM540X_AN_AD_1000BASET_FULL) { - - ethcmd.advertising |= - ADVERTISED_1000baseT_Full; - } - } - } - else { - ethcmd.autoneg = AUTONEG_DISABLE; - ethcmd.advertising = 0; - } - - ethcmd.maxtxpkt = pDevice->TxMaxCoalescedFrames; - ethcmd.maxrxpkt = pDevice->RxMaxCoalescedFrames; - - if(mm_copy_to_user(useraddr, ðcmd, sizeof(ethcmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - unsigned long flags; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (ethcmd.autoneg == AUTONEG_ENABLE) { - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_UNKNOWN; - pDevice->DisableAutoNeg = FALSE; - } - else { - if (ethcmd.speed == SPEED_1000 && - pDevice->PhyFlags & PHY_NO_GIGABIT) - return -EINVAL; - - if (ethcmd.speed == SPEED_1000 && - (pDevice->TbiFlags & ENABLE_TBI_FLAG || - pDevice->PhyFlags & PHY_IS_FIBER ) ) { - - pDevice->RequestedLineSpeed = - LM_LINE_SPEED_1000MBPS; - - pDevice->RequestedDuplexMode = - LM_DUPLEX_MODE_FULL; - } - else if (ethcmd.speed == SPEED_100 && - !(pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !(pDevice->PhyFlags & PHY_IS_FIBER)) { - - pDevice->RequestedLineSpeed = - LM_LINE_SPEED_100MBPS; - } - else if (ethcmd.speed == SPEED_10 && - !(pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !(pDevice->PhyFlags & PHY_IS_FIBER)) { - - pDevice->RequestedLineSpeed = - LM_LINE_SPEED_10MBPS; - } - else { - return -EINVAL; - } - - pDevice->DisableAutoNeg = TRUE; - if (ethcmd.duplex == DUPLEX_FULL) { - pDevice->RequestedDuplexMode = - LM_DUPLEX_MODE_FULL; - } - else { - if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !(pDevice->PhyFlags & PHY_IS_FIBER) ) { - - pDevice->RequestedDuplexMode = - LM_DUPLEX_MODE_HALF; - } - } - } - if (netif_running(dev)) { - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_SetupPhy(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - } - return 0; - } -#ifdef ETHTOOL_GWOL -#ifdef BCM_WOL - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - - if (((pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) || - (pDevice->Flags & DISABLE_D3HOT_FLAG)) { - wol.supported = 0; - wol.wolopts = 0; - } - else { - wol.supported = WAKE_MAGIC; - if (pDevice->WakeUpMode == LM_WAKE_UP_MODE_MAGIC_PACKET) - { - wol.wolopts = WAKE_MAGIC; - } - else { - wol.wolopts = 0; - } - } - if (mm_copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - if ((((pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) || - (pDevice->Flags & DISABLE_D3HOT_FLAG)) && - wol.wolopts) { - return -EINVAL; - } - - if ((wol.wolopts & ~WAKE_MAGIC) != 0) { - return -EINVAL; - } - if (wol.wolopts & WAKE_MAGIC) { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET; - pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET; - } - else { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; - pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE; - } - return 0; - } -#endif -#endif -#ifdef ETHTOOL_GLINK - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - - /* ifup only waits for 5 seconds for link up */ - /* NIC may take more than 5 seconds to establish link */ - if ((pUmDevice->delayed_link_ind > 0) && - delay_link[pUmDevice->index]) - return -EOPNOTSUPP; - - if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) { - edata.data = 1; - } - else { - edata.data = 0; - } - if (mm_copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif -#ifdef ETHTOOL_NWAY_RST - case ETHTOOL_NWAY_RST: { - LM_UINT32 phyctrl; - unsigned long flags; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (pDevice->DisableAutoNeg) { - return -EINVAL; - } - if (!netif_running(dev)) - return -EAGAIN; - BCM5700_PHY_LOCK(pUmDevice, flags); - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { - pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS; - pDevice->DisableAutoNeg = TRUE; - LM_SetupPhy(pDevice); - - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->DisableAutoNeg = FALSE; - LM_SetupPhy(pDevice); - } - else { - if ((T3_ASIC_REV(pDevice->ChipRevId) == - T3_ASIC_REV_5703) || - (T3_ASIC_REV(pDevice->ChipRevId) == - T3_ASIC_REV_5704) || - (T3_ASIC_REV(pDevice->ChipRevId) == - T3_ASIC_REV_5705)) - { - LM_ResetPhy(pDevice); - LM_SetupPhy(pDevice); - } - pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK; - LM_ReadPhy(pDevice, PHY_CTRL_REG, &phyctrl); - LM_WritePhy(pDevice, PHY_CTRL_REG, phyctrl | - PHY_CTRL_AUTO_NEG_ENABLE | - PHY_CTRL_RESTART_AUTO_NEG); - } - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - } -#endif -#ifdef ETHTOOL_GEEPROM - case ETHTOOL_GEEPROM: { - struct ethtool_eeprom eeprom; - LM_UINT32 *buf = 0; - LM_UINT32 buf1[64/4]; - int i, j, offset, len; - - if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - if (eeprom.offset >= pDevice->NvramSize) - return -EFAULT; - - /* maximum data limited */ - /* to read more, call again with a different offset */ - if (eeprom.len > 0x800) { - eeprom.len = 0x800; - if (mm_copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - return -EFAULT; - } - - if (eeprom.len > 64) { - buf = kmalloc(eeprom.len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - } - else { - buf = buf1; - } - useraddr += offsetof(struct ethtool_eeprom, data); - - offset = eeprom.offset; - len = eeprom.len; - if (offset & 3) { - offset &= 0xfffffffc; - len += (offset & 3); - } - len = (len + 3) & 0xfffffffc; - for (i = 0, j = 0; j < len; i++, j += 4) { - if (LM_NvramRead(pDevice, offset + j, buf + i) != - LM_STATUS_SUCCESS) { - break; - } - } - if (j >= len) { - buf += (eeprom.offset & 3); - i = mm_copy_to_user(useraddr, buf, eeprom.len); - } - if (eeprom.len > 64) { - kfree(buf); - } - if ((j < len) || i) - return -EFAULT; - return 0; - } - case ETHTOOL_SEEPROM: { - struct ethtool_eeprom eeprom; - LM_UINT32 buf[64/4]; - int i, offset, len; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - if ((eeprom.offset & 3) || (eeprom.len & 3) || - (eeprom.offset >= pDevice->NvramSize)) { - return -EFAULT; - } - - if ((eeprom.offset + eeprom.len) >= pDevice->NvramSize) { - eeprom.len = pDevice->NvramSize - eeprom.offset; - } - - useraddr += offsetof(struct ethtool_eeprom, data); - - len = eeprom.len; - offset = eeprom.offset; - for (; len > 0; ) { - if (len < 64) - i = len; - else - i = 64; - if (mm_copy_from_user(&buf, useraddr, i)) - return -EFAULT; - - bcm5700_intr_off(pUmDevice); - /* Prevent race condition on Grc.Mode register */ - bcm5700_poll_wait(pUmDevice); - - if (LM_NvramWriteBlock(pDevice, offset, buf, i/4) != - LM_STATUS_SUCCESS) { - bcm5700_intr_on(pUmDevice); - return -EFAULT; - } - bcm5700_intr_on(pUmDevice); - len -= i; - offset += i; - useraddr += i; - } - return 0; - } -#endif -#ifdef ETHTOOL_GREGS -#if (LINUX_VERSION_CODE >= 0x02040f) - case ETHTOOL_GREGS: { - struct ethtool_regs eregs; - LM_UINT32 *buf, *buf1; - unsigned int i; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (pDevice->Flags & UNDI_FIX_FLAG) - return -EOPNOTSUPP; - if (mm_copy_from_user(&eregs, useraddr, sizeof(eregs))) - return -EFAULT; - if (eregs.len > 0x6c00) - eregs.len = 0x6c00; - eregs.version = 0x0; - if (mm_copy_to_user(useraddr, &eregs, sizeof(eregs))) - return -EFAULT; - buf = buf1 = kmalloc(eregs.len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - bcm5700_get_reg_blk(pUmDevice, &buf, 0, 0xb0, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0xb0, 0x200, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x200, 0x8f0, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x8f0, 0xc00, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0xc00, 0xce0, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0xce0, 0x1000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1000, 0x1004, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1004, 0x1400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1400, 0x1480, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1480, 0x1800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1800, 0x1848, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1848, 0x1c00, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c00, 0x1c04, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c04, 0x2000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2000, 0x225c, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x225c, 0x2400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2400, 0x24c4, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x24c4, 0x2800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2800, 0x2804, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2804, 0x2c00, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c00, 0x2c20, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c20, 0x3000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3000, 0x3014, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3014, 0x3400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3400, 0x3408, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3408, 0x3800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3800, 0x3808, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3808, 0x3c00, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3c00, 0x3d00, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x3d00, 0x4000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4000, 0x4010, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4010, 0x4400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4400, 0x4458, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4458, 0x4800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4800, 0x4808, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4808, 0x4c00, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c00, 0x4c08, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c08, 0x5000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5000, 0x5050, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5050, 0x5400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5400, 0x5450, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5450, 0x5800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5800, 0x5a10, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x5a10, 0x6000, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x6000, 0x600c, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x600c, 0x6400, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x6400, 0x6404, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x6404, 0x6800, 1); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x6800, 0x6848, 0); - bcm5700_get_reg_blk(pUmDevice, &buf, 0x6848, 0x6c00, 1); - - i = mm_copy_to_user(useraddr + sizeof(eregs), buf1, eregs.len); - kfree(buf1); - if (i) - return -EFAULT; - return 0; - } -#endif -#endif -#ifdef ETHTOOL_GPAUSEPARAM - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM }; - - if (!pDevice->DisableAutoNeg) { - epause.autoneg = (pDevice->FlowControlCap & - LM_FLOW_CONTROL_AUTO_PAUSE) != 0; - } - else { - epause.autoneg = 0; - } - epause.rx_pause = - (pDevice->FlowControl & - LM_FLOW_CONTROL_RECEIVE_PAUSE) != 0; - epause.tx_pause = - (pDevice->FlowControl & - LM_FLOW_CONTROL_TRANSMIT_PAUSE) != 0; - if (mm_copy_to_user(useraddr, &epause, sizeof(epause))) - return -EFAULT; - - return 0; - } - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - unsigned long flags; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&epause, useraddr, sizeof(epause))) - return -EFAULT; - pDevice->FlowControlCap = 0; - if (epause.autoneg && !pDevice->DisableAutoNeg) { - pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE; - } - if (epause.rx_pause) { - pDevice->FlowControlCap |= - LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - if (epause.tx_pause) { - pDevice->FlowControlCap |= - LM_FLOW_CONTROL_TRANSMIT_PAUSE; - } - if (netif_running(dev)) { - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_SetupPhy(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - } - - return 0; - } -#endif -#ifdef ETHTOOL_GRXCSUM - case ETHTOOL_GRXCSUM: { - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = - (pDevice->TaskToOffload & - LM_TASK_OFFLOAD_RX_TCP_CHECKSUM) != 0; - if (mm_copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - - return 0; - } - case ETHTOOL_SRXCSUM: { - struct ethtool_value edata; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if (edata.data) { - if (!(pDevice->TaskOffloadCap & - LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) { - - return -EINVAL; - } - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_RX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_RX_UDP_CHECKSUM; - } - else { - pDevice->TaskToOffload &= - ~(LM_TASK_OFFLOAD_RX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_RX_UDP_CHECKSUM); - } - return 0; - } - case ETHTOOL_GTXCSUM: { - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - edata.data = - (dev->features & get_csum_flag( pDevice->ChipRevId)) != 0; - if (mm_copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - - return 0; - } - case ETHTOOL_STXCSUM: { - struct ethtool_value edata; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if (edata.data) { - if (!(pDevice->TaskOffloadCap & - LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) { - - return -EINVAL; - } - dev->features |= get_csum_flag( pDevice->ChipRevId); - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_TX_UDP_CHECKSUM; - } - else { - dev->features &= ~get_csum_flag( pDevice->ChipRevId); - pDevice->TaskToOffload &= - ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_TX_UDP_CHECKSUM); - } - return 0; - } - case ETHTOOL_GSG: { - struct ethtool_value edata = { ETHTOOL_GSG }; - - edata.data = - (dev->features & NETIF_F_SG) != 0; - if (mm_copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSG: { - struct ethtool_value edata; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if (edata.data) { - dev->features |= NETIF_F_SG; - } - else { - dev->features &= ~NETIF_F_SG; - } - return 0; - } -#endif -#ifdef ETHTOOL_GRINGPARAM - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM }; - - ering.rx_max_pending = T3_STD_RCV_RCB_ENTRY_COUNT - 1; - ering.rx_pending = pDevice->RxStdDescCnt; - ering.rx_mini_max_pending = 0; - ering.rx_mini_pending = 0; -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - ering.rx_jumbo_max_pending = T3_JUMBO_RCV_RCB_ENTRY_COUNT - 1; - ering.rx_jumbo_pending = pDevice->RxJumboDescCnt; -#else - ering.rx_jumbo_max_pending = 0; - ering.rx_jumbo_pending = 0; -#endif - ering.tx_max_pending = MAX_TX_PACKET_DESC_COUNT - 1; - ering.tx_pending = pDevice->TxPacketDescCnt; - if (mm_copy_to_user(useraddr, &ering, sizeof(ering))) - return -EFAULT; - return 0; - } -#endif -#ifdef ETHTOOL_PHYS_ID - case ETHTOOL_PHYS_ID: { - struct ethtool_value edata; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (mm_copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if (LM_BlinkLED(pDevice, edata.data) == LM_STATUS_SUCCESS) - return 0; - return -EINTR; - } -#endif -#ifdef ETHTOOL_GSTRINGS - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings egstr = { ETHTOOL_GSTRINGS }; - - if (mm_copy_from_user(&egstr, useraddr, sizeof(egstr))) - return -EFAULT; - switch(egstr.string_set) { -#ifdef ETHTOOL_GSTATS - case ETH_SS_STATS: - egstr.len = ETH_NUM_STATS; - if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr))) - return -EFAULT; - if (mm_copy_to_user(useraddr + sizeof(egstr), - bcm5700_stats_str_arr, - sizeof(bcm5700_stats_str_arr))) - return -EFAULT; - return 0; -#endif -#ifdef ETHTOOL_TEST - case ETH_SS_TEST: - egstr.len = ETH_NUM_TESTS; - if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr))) - return -EFAULT; - if (mm_copy_to_user(useraddr + sizeof(egstr), - bcm5700_tests_str_arr, - sizeof(bcm5700_tests_str_arr))) - return -EFAULT; - return 0; -#endif - default: - return -EOPNOTSUPP; - } - } -#endif -#ifdef ETHTOOL_GSTATS - case ETHTOOL_GSTATS: { - struct ethtool_stats estats = { ETHTOOL_GSTATS }; - uint64_t stats[ETH_NUM_STATS]; - int i; - uint64_t *pStats = - (uint64_t *) pDevice->pStatsBlkVirt; - - estats.n_stats = ETH_NUM_STATS; - if (pStats == 0) { - memset(stats, 0, sizeof(stats)); - } - else { - - for (i = 0; i < ETH_NUM_STATS; i++) { - if (bcm5700_stats_offset_arr[i] != 0) { - stats[i] = SWAP_DWORD_64(*(pStats + - bcm5700_stats_offset_arr[i])); - } - else if (i == RX_CRC_IDX) { - stats[i] = - bcm5700_crc_count(pUmDevice); - } - else if (i == RX_MAC_ERR_IDX) { - stats[i] = - bcm5700_rx_err_count(pUmDevice); - } - } - } - if (mm_copy_to_user(useraddr, &estats, sizeof(estats))) { - return -EFAULT; - } - if (mm_copy_to_user(useraddr + sizeof(estats), &stats, - sizeof(stats))) { - return -EFAULT; - } - return 0; - } -#endif -#ifdef ETHTOOL_TEST - case ETHTOOL_TEST: { - struct ethtool_test etest; - uint64_t tests[ETH_NUM_TESTS] = {0, 0, 0, 0, 0, 0}; - LM_POWER_STATE old_power_level; - - printk( KERN_ALERT "Performing ethtool test.\n" - "This test will take a few seconds to complete.\n" ); - - if (mm_copy_from_user(&etest, useraddr, sizeof(etest))) - return -EFAULT; - - etest.len = ETH_NUM_TESTS; - old_power_level = pDevice->PowerLevel; - if (old_power_level != LM_POWER_STATE_D0) { - LM_SetPowerState(pDevice, LM_POWER_STATE_D0); - LM_SwitchClocks(pDevice); - } - MM_Sleep(pDevice, 1000); - if (etest.flags & ETH_TEST_FL_OFFLINE) { - b57_suspend_chip(pUmDevice); - MM_Sleep(pDevice, 1000); - LM_HaltCpu(pDevice,T3_RX_CPU_ID | T3_TX_CPU_ID); - MM_Sleep(pDevice, 1000); - if (b57_test_registers(pUmDevice) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[0] = 1; - } - MM_Sleep(pDevice, 1000); - if (b57_test_memory(pUmDevice) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[1] = 1; - } - MM_Sleep(pDevice, 1000); - if (b57_test_loopback(pUmDevice, NICE_LOOPBACK_TESTTYPE_MAC, 0) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[2] = 1; - } - MM_Sleep(pDevice, 1000); - b57_resume_chip(pUmDevice); - /* wait for link to come up for the link test */ - MM_Sleep(pDevice, 4000); - if ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) && - !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) { - - /* wait a little longer for linkup on copper */ - MM_Sleep(pDevice, 3000); - } - } - if (b57_test_nvram(pUmDevice) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[3] = 1; - } - MM_Sleep(pDevice, 1000); - if (b57_test_intr(pUmDevice) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[4] = 1; - } - MM_Sleep(pDevice, 1000); - if (b57_test_link(pUmDevice) == 0) { - etest.flags |= ETH_TEST_FL_FAILED; - tests[5] = 1; - } - MM_Sleep(pDevice, 1000); - if (old_power_level != LM_POWER_STATE_D0) { - LM_SetPowerState(pDevice, old_power_level); - } - if (mm_copy_to_user(useraddr, &etest, sizeof(etest))) { - return -EFAULT; - } - if (mm_copy_to_user(useraddr + sizeof(etest), tests, - sizeof(tests))) { - return -EFAULT; - } - return 0; - } -#endif -#ifdef ETHTOOL_GTSO - case ETHTOOL_GTSO: { - struct ethtool_value edata = { ETHTOOL_GTSO }; - -#ifdef BCM_TSO - edata.data = - (dev->features & NETIF_F_TSO) != 0; -#else - edata.data = 0; -#endif - if (mm_copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } -#endif -#ifdef ETHTOOL_STSO - case ETHTOOL_STSO: { -#ifdef BCM_TSO - struct ethtool_value edata; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (mm_copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - if (!(pDevice->TaskToOffload & - LM_TASK_OFFLOAD_TCP_SEGMENTATION)) { - return -EINVAL; - } - - dev->features &= ~NETIF_F_TSO; - - if (edata.data) { - if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) && - (dev->mtu > 1500)) { - printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name); - return -EINVAL; - } else { - dev->features |= NETIF_F_TSO; - } - } - return 0; -#else - return -EINVAL; -#endif - } -#endif - } - - return -EOPNOTSUPP; -} -#endif /* #ifdef SIOCETHTOOL */ - -#if (LINUX_VERSION_CODE >= 0x20400) && (LINUX_VERSION_CODE < 0x20600) -#include -#endif - -#ifdef BCMDBG -STATIC void -b57_dump(struct net_device *dev, struct bcmstrbuf *b) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - struct net_device_stats *st; - char macaddr[32]; - - bcm_bprintf(b, "b57%d: %s %s version %s\n", pUmDevice->index, - __DATE__, __TIME__, EPI_VERSION_STR); - - bcm_bprintf(b, "dev 0x%x pdev 0x%x unit %d msglevel %d flags 0x%x boardflags 0x%x\n", - (uint)dev, (uint)pDevice, pUmDevice->index, b57_msg_level, - pDevice->Flags, pUmDevice->boardflags); - bcm_bprintf(b, "speed/duplex %d/%s promisc 0x%x loopbk %d advertise 0x%x\n", - pDevice->LineSpeed, - (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) ? "full" : "half", - pDevice->ReceiveMask & LM_PROMISCUOUS_MODE, - pDevice->LoopBackMode, - pDevice->advertising); - bcm_bprintf(b, "allmulti %d qos %d phyaddr %d linkstat %d\n", - pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST, pUmDevice->qos, - pDevice->PhyAddr, pDevice->LinkStatus); - bcm_bprintf(b, "vendor 0x%x device 0x%x rev %d subsys vendor 0x%x subsys id 0x%x\n", - pDevice->PciVendorId, pDevice->PciDeviceId, pDevice->PciRevId, - pDevice->SubsystemVendorId, pDevice->SubsystemId); - bcm_bprintf(b, "MAC addr %s\n", bcm_ether_ntoa((struct ether_addr *)&pDevice->NodeAddress, - macaddr)); - - if ((st = bcm5700_get_stats(dev)) != NULL) { - bcm_bprintf(b, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %d\n", - st->tx_packets, st->tx_bytes, st->tx_errors, - st->rx_packets, st->rx_bytes, st->rx_errors); - bcm_bprintf(b, "multicast %d collisions %d tx_abort %d tx_carrier %d\n", - st->multicast, st->collisions, st->tx_aborted_errors, - st->tx_carrier_errors); - bcm_bprintf(b, "rx_length %d rx_over %d rx_frame %d rx_crc %d\n", - st->rx_length_errors, st->rx_over_errors, st->rx_frame_errors, - st->rx_crc_errors); - } - if (pDevice->Flags & ROBO_SWITCH_FLAG) - robo_dump_regs(pUmDevice->robo, b); - - bcm_bprintf(b, "\n"); -} -#endif /* BCMDBG */ - -/* Provide ioctl() calls to examine the MII xcvr state. */ -STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - u16 *data = (u16 *)&rq->ifr_data; - u32 value; - unsigned long flags; - - switch(cmd) { -#ifdef SIOCGMIIPHY - case SIOCGMIIPHY: /* Get the address of the PHY in use. */ - - data[0] = pDevice->PhyAddr; - return 0; -#endif - -#ifdef SIOCGMIIREG - case SIOCGMIIREG: /* Read the specified MII register. */ - { - uint32 savephyaddr = 0; - - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - return -EOPNOTSUPP; - - /* ifup only waits for 5 seconds for link up */ - /* NIC may take more than 5 seconds to establish link */ - if ((pUmDevice->delayed_link_ind > 0) && - delay_link[pUmDevice->index]) { - return -EAGAIN; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - if (data[0] != 0xffff) { - savephyaddr = pDevice->PhyAddr; - pDevice->PhyAddr = data[0]; - } - LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *)&value); - if (data[0] != 0xffff) - pDevice->PhyAddr = savephyaddr; - BCM5700_PHY_UNLOCK(pUmDevice, flags); - data[3] = value & 0xffff; - return 0; - } -#endif - - case SIOCGETCPHYRD: /* Read the specified MII register. */ - case SIOCGETCPHYRD2: - { - int args[2]; - uint32 savephyaddr = 0; - - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - return -EOPNOTSUPP; - - /* ifup only waits for 5 seconds for link up */ - /* NIC may take more than 5 seconds to establish link */ - if ((pUmDevice->delayed_link_ind > 0) && - delay_link[pUmDevice->index]) { - return -EAGAIN; - } - - if (mm_copy_from_user(&args, rq->ifr_data, sizeof(args))) - return -EFAULT; - - BCM5700_PHY_LOCK(pUmDevice, flags); - if (cmd == SIOCGETCPHYRD2) { - savephyaddr = pDevice->PhyAddr; - pDevice->PhyAddr = (args[0] >> 16) & 0xffff; - } - LM_ReadPhy(pDevice, args[0] & 0xffff, (LM_UINT32 *)&value); - if (cmd == SIOCGETCPHYRD2) - pDevice->PhyAddr = savephyaddr; - BCM5700_PHY_UNLOCK(pUmDevice, flags); - - args[1] = value & 0xffff; - if (mm_copy_to_user(rq->ifr_data, &args, sizeof(args))) - return -EFAULT; - - return 0; - } - -#ifdef SIOCSMIIREG - case SIOCSMIIREG: /* Write the specified MII register */ - { - uint32 savephyaddr = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - return -EOPNOTSUPP; - - BCM5700_PHY_LOCK(pUmDevice, flags); - if (data[0] != 0xffff) { - savephyaddr = pDevice->PhyAddr; - pDevice->PhyAddr = data[0]; - } - LM_WritePhy(pDevice, data[1] & 0x1f, data[2]); - if (data[0] != 0xffff) - pDevice->PhyAddr = savephyaddr; - BCM5700_PHY_UNLOCK(pUmDevice, flags); - data[3] = 0; - return 0; - } -#endif - - case SIOCSETCPHYWR: /* Write the specified MII register */ - case SIOCSETCPHYWR2: - { - int args[2]; - uint32 savephyaddr = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) - return -EOPNOTSUPP; - - if (mm_copy_from_user(&args, rq->ifr_data, sizeof(args))) - return -EFAULT; - - BCM5700_PHY_LOCK(pUmDevice, flags); - if (cmd == SIOCSETCPHYWR2) { - savephyaddr = pDevice->PhyAddr; - pDevice->PhyAddr = (args[0] >> 16) & 0xffff; - } - LM_WritePhy(pDevice, args[0] & 0xffff, args[1]); - if (cmd == SIOCSETCPHYWR2) - pDevice->PhyAddr = savephyaddr; - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - } - - case SIOCGETCROBORD: /* Read the specified ROBO register. */ - { - int args[2]; - robo_info_t *robo = (robo_info_t *)pUmDevice->robo; - - if (((pDevice->Flags & ROBO_SWITCH_FLAG) == 0) || (robo == NULL)) - return -ENXIO; - - if (mm_copy_from_user(&args, rq->ifr_data, sizeof(args))) - return -EFAULT; - - if (robo->ops->read_reg(robo, (args[0] >> 16) & 0xffff, args[0] & 0xffff, &value, 2)) - return -EIO; - - args[1] = value & 0xffff; - if (mm_copy_to_user(rq->ifr_data, &args, sizeof(args))) - return -EFAULT; - - return 0; - } - - case SIOCSETCROBOWR: /* Write the specified ROBO register. */ - { - int args[2]; - robo_info_t *robo = (robo_info_t *)pUmDevice->robo; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (((pDevice->Flags & ROBO_SWITCH_FLAG) == 0) || (robo == NULL)) - return -ENXIO; - - if (mm_copy_from_user(&args, rq->ifr_data, sizeof(args))) - return -EFAULT; - - if (robo->ops->write_reg(robo, (args[0] >> 16) & 0xffff, args[0] & 0xffff, - &args[1], 2)) - return -EIO; - - return 0; - } - - case SIOCSETGETVAR: - { - int ret = 0; - void *buffer = NULL; - bool get = FALSE, set = TRUE; - et_var_t var; - - if (set && mm_copy_from_user(&var, rq->ifr_data, sizeof(var))) - return -EFAULT; - - /* prepare buffer if any */ - if (var.buf) { - if (!var.set) - get = TRUE; - - if (!(buffer = (void *) MALLOC(SI_OSH, var.len))) { - B57_ERR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, - MALLOCED(SI_OSH))); - return -ENOMEM; - } - - if (mm_copy_from_user(buffer, var.buf, var.len)) { - MFREE(SI_OSH, buffer, var.len); - return -EFAULT; - } - } - - /* do var.cmd */ - switch (var.cmd) { - case IOV_ET_ROBO_DEVID: - { - uint *vecarg = (uint *)buffer; - robo_info_t *robo = (robo_info_t *)pUmDevice->robo; - - if (((pDevice->Flags & ROBO_SWITCH_FLAG) == 0) || - (robo == NULL)) { - ret = -ENXIO; - break; - } - - /* get robo device id */ - *vecarg = robo->devid; - - if (mm_copy_to_user(var.buf, buffer, var.len)) { - ret = -EFAULT; - break; - } - - break; - } - - default: - ret = -EOPNOTSUPP; - break; - } - - if (buffer) - MFREE(SI_OSH, buffer, var.len); - - return ret; - } - - case SIOCSETCSETMSGLEVEL: - if (mm_copy_from_user(&value, rq->ifr_data, sizeof(value))) - return -EFAULT; - - b57_msg_level = value; - printf("%s: msglevel set to 0x%x\n", __FUNCTION__, b57_msg_level); - return 0; - - case SIOCSETCQOS: /* Set the qos flag */ - if (mm_copy_from_user(&value, rq->ifr_data, sizeof(value))) - return -EFAULT; - - pUmDevice->qos = value; - B57_INFO(("Qos flag now: %d\n", pUmDevice->qos)); - return 0; - - case SIOCGETCDUMP: - { - char *buf; - - if ((buf = MALLOC(SI_OSH, 4096)) == NULL) { - B57_ERR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, - MALLOCED(SI_OSH))); - return (-ENOMEM); - } - - if (b57_msg_level & 0x10000) - bcmdumplog(buf, 4096); -#ifdef BCMDBG - else { - struct bcmstrbuf b; - bcm_binit(&b, buf, 4096); - b57_dump(dev, &b); - } -#endif /* BCMDBG */ - value = mm_copy_to_user(rq->ifr_data, buf, 4096); - - MFREE(SI_OSH, buf, 4096); - - if (value) - return -EFAULT; - else - return 0; - } - -#ifdef NICE_SUPPORT - case SIOCNICE: - { - struct nice_req* nrq; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - nrq = (struct nice_req*)&rq->ifr_ifru; - if( nrq->cmd == NICE_CMD_QUERY_SUPPORT ) { - nrq->nrq_magic = NICE_DEVICE_MAGIC; - nrq->nrq_support_rx = 1; - nrq->nrq_support_vlan = 1; - nrq->nrq_support_get_speed = 1; -#ifdef BCM_NAPI_RXPOLL - nrq->nrq_support_rx_napi = 1; -#endif - return 0; - } -#ifdef BCM_NAPI_RXPOLL - else if( nrq->cmd == NICE_CMD_SET_RX_NAPI ) -#else - else if( nrq->cmd == NICE_CMD_SET_RX ) -#endif - { - pUmDevice->nice_rx = nrq->nrq_rx; - pUmDevice->nice_ctx = nrq->nrq_ctx; - bcm5700_set_vlan_mode(pUmDevice); - return 0; - } -#ifdef BCM_NAPI_RXPOLL - else if( nrq->cmd == NICE_CMD_GET_RX_NAPI ) -#else - else if( nrq->cmd == NICE_CMD_GET_RX ) -#endif - { - nrq->nrq_rx = pUmDevice->nice_rx; - nrq->nrq_ctx = pUmDevice->nice_ctx; - return 0; - } - else if( nrq->cmd == NICE_CMD_GET_SPEED ) { - if(pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE){ - nrq->nrq_speed = 0; - } - else if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) { - nrq->nrq_speed = SPEED_1000; - } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) { - nrq->nrq_speed = SPEED_100; - } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { - nrq->nrq_speed = SPEED_100; - } else { - nrq->nrq_speed = 0; - } - return 0; - } - else { - if (!pUmDevice->opened) - return -EINVAL; - - switch (nrq->cmd) { - case NICE_CMD_BLINK_LED: - if (LM_BlinkLED(pDevice, nrq->nrq_blink_time) == - LM_STATUS_SUCCESS) { - return 0; - } - return -EINTR; - - case NICE_CMD_DIAG_SUSPEND: - b57_suspend_chip(pUmDevice); - return 0; - - case NICE_CMD_DIAG_RESUME: - b57_resume_chip(pUmDevice); - return 0; - - case NICE_CMD_REG_READ: - if (nrq->nrq_offset >= 0x10000) { - nrq->nrq_data = LM_RegRdInd(pDevice, - nrq->nrq_offset); - } - else { - nrq->nrq_data = LM_RegRd(pDevice, - nrq->nrq_offset); - } - return 0; - - case NICE_CMD_REG_WRITE: - if (nrq->nrq_offset >= 0x10000) { - LM_RegWrInd(pDevice, nrq->nrq_offset, - nrq->nrq_data); - } - else { - LM_RegWr(pDevice, nrq->nrq_offset, - nrq->nrq_data, FALSE); - } - return 0; - - case NICE_CMD_REG_READ_DIRECT: - case NICE_CMD_REG_WRITE_DIRECT: - if ((nrq->nrq_offset >= 0x10000) || - (pDevice->Flags & UNDI_FIX_FLAG)) { - return -EINVAL; - } - - if (nrq->cmd == NICE_CMD_REG_READ_DIRECT) { - nrq->nrq_data = REG_RD_OFFSET(pDevice, - nrq->nrq_offset); - } - else { - REG_WR_OFFSET(pDevice, nrq->nrq_offset, - nrq->nrq_data); - } - return 0; - - case NICE_CMD_MEM_READ: - nrq->nrq_data = LM_MemRdInd(pDevice, - nrq->nrq_offset); - return 0; - - case NICE_CMD_MEM_WRITE: - LM_MemWrInd(pDevice, nrq->nrq_offset, - nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_READ32: - pci_read_config_dword(pUmDevice->pdev, - nrq->nrq_offset, (u32 *)&nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_READ16: - pci_read_config_word(pUmDevice->pdev, - nrq->nrq_offset, (u16 *)&nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_READ8: - pci_read_config_byte(pUmDevice->pdev, - nrq->nrq_offset, (u8 *)&nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_WRITE32: - pci_write_config_dword(pUmDevice->pdev, - nrq->nrq_offset, (u32)nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_WRITE16: - pci_write_config_word(pUmDevice->pdev, - nrq->nrq_offset, (u16)nrq->nrq_data); - return 0; - - case NICE_CMD_CFG_WRITE8: - pci_write_config_byte(pUmDevice->pdev, - nrq->nrq_offset, (u8)nrq->nrq_data); - return 0; - - case NICE_CMD_RESET: - bcm5700_reset(dev); - return 0; - - case NICE_CMD_ENABLE_MAC_LOOPBACK: - if (pDevice->LoopBackMode != 0) { - return -EINVAL; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_EnableMacLoopBack(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_DISABLE_MAC_LOOPBACK: - if (pDevice->LoopBackMode != - LM_MAC_LOOP_BACK_MODE) { - return -EINVAL; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_DisableMacLoopBack(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_ENABLE_PHY_LOOPBACK: - if (pDevice->LoopBackMode != 0) { - return -EINVAL; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_EnablePhyLoopBack(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_DISABLE_PHY_LOOPBACK: - if (pDevice->LoopBackMode != - LM_PHY_LOOP_BACK_MODE) { - return -EINVAL; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_DisablePhyLoopBack(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_ENABLE_EXT_LOOPBACK: - if (pDevice->LoopBackMode != 0) { - return -EINVAL; - } - - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { - if (nrq->nrq_speed != 1000) - return -EINVAL; - } - else { - if ((nrq->nrq_speed != 1000) && - (nrq->nrq_speed != 100) && - (nrq->nrq_speed != 10)) { - return -EINVAL; - } - } - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_EnableExtLoopBack(pDevice, nrq->nrq_speed); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_DISABLE_EXT_LOOPBACK: - if (pDevice->LoopBackMode != - LM_EXT_LOOP_BACK_MODE) { - return -EINVAL; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - LM_DisableExtLoopBack(pDevice); - BCM5700_PHY_UNLOCK(pUmDevice, flags); - return 0; - - case NICE_CMD_INTERRUPT_TEST: - nrq->nrq_intr_test_result = - b57_test_intr(pUmDevice); - return 0; - - case NICE_CMD_LOOPBACK_TEST: - value = 0; - switch (nrq->nrq_looptype) { - case NICE_LOOPBACK_TESTTYPE_EXT: - if ((nrq->nrq_loopspeed & ~NICE_LOOPBACK_TEST_SPEEDMASK) || - !(nrq->nrq_loopspeed & NICE_LOOPBACK_TEST_SPEEDMASK)) - break; - switch (nrq->nrq_loopspeed) { - case NICE_LOOPBACK_TEST_10MBPS: - value = LM_LINE_SPEED_10MBPS; - break; - case NICE_LOOPBACK_TEST_100MBPS: - value = LM_LINE_SPEED_100MBPS; - break; - case NICE_LOOPBACK_TEST_1000MBPS: - value = LM_LINE_SPEED_1000MBPS; - break; - } - /* Fall through */ - - case NICE_LOOPBACK_TESTTYPE_MAC: - case NICE_LOOPBACK_TESTTYPE_PHY: - b57_suspend_chip(pUmDevice); - value = b57_test_loopback(pUmDevice, - nrq->nrq_looptype, value); - b57_resume_chip(pUmDevice); - break; - } - - if (value == 1) { - /* A '1' indicates success */ - value = 0; - } else { - value = -EINTR; - } - - return value; - - case NICE_CMD_KMALLOC_PHYS: { -#if (LINUX_VERSION_CODE >= 0x020400) - dma_addr_t mapping; - __u64 cpu_pa; - void *ptr; - int i; - struct page *pg, *last_pg; - - for (i = 0; i < MAX_MEM2; i++) { - if (pUmDevice->mem_size_list2[i] == 0) - break; - } - if (i >= MAX_MEM2) - return -EFAULT; - ptr = pci_alloc_consistent(pUmDevice->pdev, - nrq->nrq_size, &mapping); - if (!ptr) { - return -EFAULT; - } - pUmDevice->mem_size_list2[i] = nrq->nrq_size; - pUmDevice->mem_list2[i] = ptr; - pUmDevice->dma_list2[i] = mapping; - - /* put pci mapping at the beginning of buffer */ - *((__u64 *) ptr) = (__u64) mapping; - - /* Probably won't work on some architectures */ - /* get CPU mapping */ - cpu_pa = (__u64) virt_to_phys(ptr); - pUmDevice->cpu_pa_list2[i] = cpu_pa; - nrq->nrq_phys_addr_lo = (__u32) cpu_pa; - nrq->nrq_phys_addr_hi = (__u32) (cpu_pa >> 32); - - pg = virt_to_page(ptr); - last_pg = virt_to_page(ptr + nrq->nrq_size - 1); - for (; ; pg++) { -#if (LINUX_VERSION_CODE > 0x020500) - SetPageReserved(pg); -#else - mem_map_reserve(pg); -#endif - if (pg == last_pg) - break; - } - return 0; -#else - return -EOPNOTSUPP; -#endif - } - - case NICE_CMD_KFREE_PHYS: { - int i; - __u64 cpu_pa; - - cpu_pa = (__u64) nrq->nrq_phys_addr_lo + - ((__u64) nrq->nrq_phys_addr_hi << 32); - for (i = 0; i < MAX_MEM2; i++) { - if (pUmDevice->cpu_pa_list2[i] == - cpu_pa) - { - break; - } - } - if (i >= MAX_MEM2) - return -EFAULT; - - bcm5700_freemem2(pUmDevice, i); - return 0; - } - - case NICE_CMD_SET_WRITE_PROTECT: - if (nrq->nrq_write_protect) - pDevice->Flags |= EEPROM_WP_FLAG; - else - pDevice->Flags &= ~EEPROM_WP_FLAG; - return 0; - case NICE_CMD_GET_STATS_BLOCK: { - PT3_STATS_BLOCK pStats = - (PT3_STATS_BLOCK)pDevice->pStatsBlkVirt; - if (mm_copy_to_user(nrq->nrq_stats_useraddr, - pStats, nrq->nrq_stats_size)) { - return -EFAULT; - } - return 0; - } - case NICE_CMD_CLR_STATS_BLOCK: { - int j; - PT3_STATS_BLOCK pStats = - (PT3_STATS_BLOCK)pDevice->pStatsBlkVirt; - - memset(pStats, 0, sizeof(T3_STATS_BLOCK)); - if (T3_ASIC_REV(pDevice->ChipRevId) == - T3_ASIC_REV_5705) { - return 0; - } - for(j = 0x0300; j < 0x0b00; j = j + 4) { - MEM_WR_OFFSET(pDevice, j, 0); - } - - return 0; - } - - } - } - return -EOPNOTSUPP; - } -#endif /* NICE_SUPPORT */ -#ifdef SIOCETHTOOL - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); -#endif - default: - return -EOPNOTSUPP; - } - return -EOPNOTSUPP; -} - -STATIC void bcm5700_do_rx_mode(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - int i; - struct dev_mc_list *mclist; - - LM_MulticastClear(pDevice); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr); - } - if (dev->flags & IFF_ALLMULTI) { - if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST); - } - } - else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST); - } - if (dev->flags & IFF_PROMISC) { - if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask | LM_PROMISCUOUS_MODE); - } - } - else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE); - } - -} - -STATIC void bcm5700_set_rx_mode(struct net_device *dev) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - int i; - struct dev_mc_list *mclist; - unsigned long flags; - - BCM5700_PHY_LOCK(pUmDevice, flags); - - LM_MulticastClear(pDevice); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr); - } - if (dev->flags & IFF_ALLMULTI) { - if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST); - } - } - else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST); - } - if (dev->flags & IFF_PROMISC) { - if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask | LM_PROMISCUOUS_MODE); - } - } - else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE); - } - - BCM5700_PHY_UNLOCK(pUmDevice, flags); -} - -/* - * Set the hardware MAC address. - */ -STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr=p; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) dev->priv; - UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - - if(is_valid_ether_addr(addr->sa_data)){ - - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - if (pUmDevice->opened) - LM_SetMacAddress(pDevice, dev->dev_addr); - return 0; - } - return -EINVAL; -} - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu) -{ - int pkt_size = new_mtu + ETHERNET_PACKET_HEADER_SIZE; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv; - PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev; - unsigned long flags; - int reinit = 0; - - if ((pkt_size < MIN_ETHERNET_PACKET_SIZE_NO_CRC) || - (pkt_size > MAX_ETHERNET_JUMBO_PACKET_SIZE_NO_CRC)) { - - return -EINVAL; - } - if ( !(pDevice->Flags & JUMBO_CAPABLE_FLAG) && - (pkt_size > MAX_ETHERNET_PACKET_SIZE_NO_CRC) ) { - - return -EINVAL; - } - if (pUmDevice->suspended) - return -EAGAIN; - - if (pUmDevice->opened && (new_mtu != dev->mtu) && - (pDevice->Flags & JUMBO_CAPABLE_FLAG)) { - reinit = 1; - } - - BCM5700_PHY_LOCK(pUmDevice, flags); - if (reinit) { - netif_stop_queue(dev); - bcm5700_shutdown(pUmDevice); - bcm5700_freemem(dev); - } - - dev->mtu = new_mtu; - if (pkt_size < MAX_ETHERNET_PACKET_SIZE_NO_CRC) { - pDevice->RxMtu = pDevice->TxMtu = - MAX_ETHERNET_PACKET_SIZE_NO_CRC; - } - else { - pDevice->RxMtu = pDevice->TxMtu = pkt_size; - } - - if (dev->mtu <= 1514) { - pDevice->RxJumboDescCnt = 0; - } - else if (pDevice->Flags & JUMBO_CAPABLE_FLAG){ - pDevice->RxJumboDescCnt = - rx_jumbo_desc_cnt[pUmDevice->index]; - } - pDevice->RxPacketDescCnt = pDevice->RxJumboDescCnt + - pDevice->RxStdDescCnt; - - pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ + - COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK; - -#ifdef BCM_TSO - if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) && - (dev->mtu > 1514) ) { - if (dev->features & NETIF_F_TSO) { - dev->features &= ~NETIF_F_TSO; - printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name); - } - } -#endif - - if (reinit) { - LM_InitializeAdapter(pDevice); - bcm5700_do_rx_mode(dev); - bcm5700_set_vlan_mode(pUmDevice); - bcm5700_init_counters(pUmDevice); - if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) { - LM_SetMacAddress(pDevice, dev->dev_addr); - } - netif_start_queue(dev); - bcm5700_intr_on(pUmDevice); - } - BCM5700_PHY_UNLOCK(pUmDevice, flags); - - return 0; -} -#endif - - -#if (LINUX_VERSION_CODE < 0x020300) -int -bcm5700_probe(struct net_device *dev) -{ - int cards_found = 0; - struct pci_dev *pdev = NULL; - struct pci_device_id *pci_tbl; - u16 ssvid, ssid; - - if ( ! pci_present()) - return -ENODEV; - - pci_tbl = bcm5700_pci_tbl; - while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) { - int idx; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &ssvid); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &ssid); - for (idx = 0; pci_tbl[idx].vendor; idx++) { - if ((pci_tbl[idx].vendor == PCI_ANY_ID || - pci_tbl[idx].vendor == pdev->vendor) && - (pci_tbl[idx].device == PCI_ANY_ID || - pci_tbl[idx].device == pdev->device) && - (pci_tbl[idx].subvendor == PCI_ANY_ID || - pci_tbl[idx].subvendor == ssvid) && - (pci_tbl[idx].subdevice == PCI_ANY_ID || - pci_tbl[idx].subdevice == ssid)) - { - - break; - } - } - if (pci_tbl[idx].vendor == 0) - continue; - - - if (bcm5700_init_one(pdev, &pci_tbl[idx]) == 0) - cards_found++; - } - - return cards_found ? 0 : -ENODEV; -} - -#ifdef MODULE -int init_module(void) -{ - return bcm5700_probe(NULL); -} - -void cleanup_module(void) -{ - struct net_device *next_dev; - PUM_DEVICE_BLOCK pUmDevice; - -#ifdef BCM_PROC_FS - bcm5700_proc_remove_notifier(); -#endif - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (root_tigon3_dev) { - pUmDevice = (PUM_DEVICE_BLOCK)root_tigon3_dev->priv; -#ifdef BCM_PROC_FS - bcm5700_proc_remove_dev(root_tigon3_dev); -#endif - next_dev = pUmDevice->next_module; - unregister_netdev(root_tigon3_dev); - if (pUmDevice->lm_dev.pMappedMemBase) - iounmap(pUmDevice->lm_dev.pMappedMemBase); -#if (LINUX_VERSION_CODE < 0x020600) - kfree(root_tigon3_dev); -#else - free_netdev(root_tigon3_dev); -#endif - root_tigon3_dev = next_dev; - } -#ifdef BCM_IOCTL32 - unregister_ioctl32_conversion(SIOCNICE); -#endif -} - -#endif /* MODULE */ -#else /* LINUX_VERSION_CODE < 0x020300 */ - -#if (LINUX_VERSION_CODE >= 0x020406) -static int bcm5700_suspend (struct pci_dev *pdev, DRV_SUSPEND_STATE_TYPE state) -#else -static void bcm5700_suspend (struct pci_dev *pdev) -#endif -{ - struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev); - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev; - - if (!netif_running(dev)) -#if (LINUX_VERSION_CODE >= 0x020406) - return 0; -#else - return; -#endif - - netif_device_detach (dev); - bcm5700_shutdown(pUmDevice); - - LM_SetPowerState(pDevice, LM_POWER_STATE_D3); - -/* pci_power_off(pdev, -1);*/ -#if (LINUX_VERSION_CODE >= 0x020406) - return 0; -#endif -} - - -#if (LINUX_VERSION_CODE >= 0x020406) -static int bcm5700_resume(struct pci_dev *pdev) -#else -static void bcm5700_resume(struct pci_dev *pdev) -#endif -{ - struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev); - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv; - PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev; - - if (!netif_running(dev)) -#if (LINUX_VERSION_CODE >= 0x020406) - return 0; -#else - return; -#endif -/* pci_power_on(pdev);*/ - netif_device_attach(dev); - LM_SetPowerState(pDevice, LM_POWER_STATE_D0); - MM_InitializeUmPackets(pDevice); - bcm5700_reset(dev); -#if (LINUX_VERSION_CODE >= 0x020406) - return 0; -#endif -} - - -static struct pci_driver bcm5700_pci_driver = { - name: bcm5700_driver, - id_table: bcm5700_pci_tbl, - probe: bcm5700_init_one, - remove: __devexit_p(bcm5700_remove_one), - suspend: bcm5700_suspend, - resume: bcm5700_resume, -}; - -static int -bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused) -{ - switch (event) { - case SYS_HALT: - case SYS_POWER_OFF: - case SYS_RESTART: - break; - default: - return NOTIFY_DONE; - } - - B57_INFO(("bcm5700 reboot notification\n")); - pci_unregister_driver(&bcm5700_pci_driver); - return NOTIFY_DONE; -} - -static int __init bcm5700_init_module (void) -{ - if (msglevel != 0xdeadbeef) { - b57_msg_level = msglevel; - printf("%s: msglevel set to 0x%x\n", __FUNCTION__, b57_msg_level); - } else - b57_msg_level = B57_ERR_VAL; - - return pci_module_init(&bcm5700_pci_driver); -} - -static void __exit bcm5700_cleanup_module (void) -{ -#ifdef BCM_PROC_FS - bcm5700_proc_remove_notifier(); -#endif - unregister_reboot_notifier(&bcm5700_reboot_notifier); - pci_unregister_driver(&bcm5700_pci_driver); -} - -module_init(bcm5700_init_module); -module_exit(bcm5700_cleanup_module); -#endif - -/* - * Middle Module - * - */ - - -#ifdef BCM_NAPI_RXPOLL -LM_STATUS -MM_ScheduleRxPoll(LM_DEVICE_BLOCK *pDevice) -{ - struct net_device *dev = ((UM_DEVICE_BLOCK *) pDevice)->dev; - - if (netif_rx_schedule_prep(dev)) { - __netif_rx_schedule(dev); - return LM_STATUS_SUCCESS; - } - return LM_STATUS_FAILURE; -} -#endif - -LM_STATUS -MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT16 *pValue16) -{ - UM_DEVICE_BLOCK *pUmDevice; - - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_read_config_word(pUmDevice->pdev, Offset, (u16 *) pValue16); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT32 *pValue32) -{ - UM_DEVICE_BLOCK *pUmDevice; - - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_read_config_dword(pUmDevice->pdev, Offset, (u32 *) pValue32); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT16 Value16) -{ - UM_DEVICE_BLOCK *pUmDevice; - - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_write_config_word(pUmDevice->pdev, Offset, Value16); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT32 Value32) -{ - UM_DEVICE_BLOCK *pUmDevice; - - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_write_config_dword(pUmDevice->pdev, Offset, Value32); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, - PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, - LM_BOOL Cached) -{ - PLM_VOID pvirt; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - dma_addr_t mapping; - - pvirt = pci_alloc_consistent(pUmDevice->pdev, BlockSize, - &mapping); - if (!pvirt) { - return LM_STATUS_FAILURE; - } - pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; - pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping; - pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; - memset(pvirt, 0, BlockSize); - *pMemoryBlockVirt = (PLM_VOID) pvirt; - MM_SetAddr(pMemoryBlockPhy, mapping); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, - PLM_VOID *pMemoryBlockVirt) -{ - PLM_VOID pvirt; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - - - /* Maximum in slab.c */ - if (BlockSize > 131072) { - goto MM_Alloc_error; - } - - pvirt = kmalloc(BlockSize, GFP_ATOMIC); - if (!pvirt) { - goto MM_Alloc_error; - } - pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; - pUmDevice->dma_list[pUmDevice->mem_list_num] = 0; - pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = 0; - /* mem_size_list[i] == 0 indicates that the memory should be freed */ - /* using kfree */ - memset(pvirt, 0, BlockSize); - *pMemoryBlockVirt = pvirt; - return LM_STATUS_SUCCESS; - -MM_Alloc_error: - printk(KERN_WARNING "%s: Memory allocation failed - buffer parameters may be set too high\n", pUmDevice->dev->name); - return LM_STATUS_FAILURE; -} - -LM_STATUS -MM_MapMemBase(PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - - pDevice->pMappedMemBase = ioremap_nocache( - pci_resource_start(pUmDevice->pdev, 0), sizeof(T3_STD_MEM_MAP)); - if (pDevice->pMappedMemBase == 0) - return LM_STATUS_FAILURE; - - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice) -{ - unsigned int i; - struct sk_buff *skb; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PUM_PACKET pUmPacket; - PLM_PACKET pPacket; - - for (i = 0; i < pDevice->RxPacketDescCnt; i++) { - pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container); - pUmPacket = (PUM_PACKET) pPacket; - if (pPacket == 0) { - printk(KERN_DEBUG "Bad RxPacketFreeQ\n"); - } - if (pUmPacket->skbuff == 0) { -#ifdef BCM_WL_EMULATOR - skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2); -#else - skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR); -#endif - if (skb == 0) { - pUmPacket->skbuff = 0; - QQ_PushTail( - &pUmDevice->rx_out_of_buf_q.Container, - pPacket); - continue; - } - pUmPacket->skbuff = skb; - skb->dev = pUmDevice->dev; -#ifndef BCM_WL_EMULATOR - skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align); -#endif - } - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); - } - if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) { - /* reallocate buffers in the ISR */ - pUmDevice->rx_buf_repl_thresh = 0; - pUmDevice->rx_buf_repl_panic_thresh = 0; - pUmDevice->rx_buf_repl_isr_limit = 0; - } - else { - pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 8; - pUmDevice->rx_buf_repl_panic_thresh = - pDevice->RxPacketDescCnt * 7 / 8; - - /* This limits the time spent in the ISR when the receiver */ - /* is in a steady state of being overrun. */ - pUmDevice->rx_buf_repl_isr_limit = pDevice->RxPacketDescCnt / 8; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - if (pDevice->RxJumboDescCnt != 0) { - if (pUmDevice->rx_buf_repl_thresh >= - pDevice->RxJumboDescCnt) { - - pUmDevice->rx_buf_repl_thresh = - pUmDevice->rx_buf_repl_panic_thresh = - pDevice->RxJumboDescCnt - 1; - } - if (pUmDevice->rx_buf_repl_thresh >= - pDevice->RxStdDescCnt) { - - pUmDevice->rx_buf_repl_thresh = - pUmDevice->rx_buf_repl_panic_thresh = - pDevice->RxStdDescCnt - 1; - } - } -#endif - } - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_GetConfig(PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - int index = pUmDevice->index; - struct net_device *dev = pUmDevice->dev; - - if (index >= MAX_UNITS) - return LM_STATUS_SUCCESS; - -#if LINUX_KERNEL_VERSION < 0x0020609 - - bcm5700_validate_param_range(pUmDevice, &auto_speed[index], "auto_speed", - 0, 1, 1); - if (auto_speed[index] == 0) - pDevice->DisableAutoNeg = TRUE; - else - pDevice->DisableAutoNeg = FALSE; - - if (line_speed[index] == 0) { - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->DisableAutoNeg = FALSE; - } - else { - bcm5700_validate_param_range(pUmDevice, &full_duplex[index], - "full_duplex", 0, 1, 1); - if (full_duplex[index]) { - pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL; - } - else { - pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_HALF; - } - - if (line_speed[index] == 1000) { - pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS; - if (pDevice->PhyFlags & PHY_NO_GIGABIT) { - pDevice->RequestedLineSpeed = - LM_LINE_SPEED_100MBPS; - printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (1000), using 100\n", bcm5700_driver, index); - } - else { - if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !full_duplex[index]) { - printk(KERN_WARNING "%s-%d: Invalid full_duplex parameter (0) for fiber, using 1\n", bcm5700_driver, index); - pDevice->RequestedDuplexMode = - LM_DUPLEX_MODE_FULL; - } - - if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) && - !auto_speed[index] && !(pDevice->PhyFlags & PHY_IS_FIBER) ) { - printk(KERN_WARNING "%s-%d: Invalid auto_speed parameter (0) for copper, using 1\n", bcm5700_driver, index); - pDevice->DisableAutoNeg = FALSE; - } - } - } - else if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) || - (pDevice->PhyFlags & PHY_IS_FIBER)){ - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL; - pDevice->DisableAutoNeg = FALSE; - printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using auto\n", bcm5700_driver, index, line_speed[index]); - } - else if (line_speed[index] == 100) { - - pDevice->RequestedLineSpeed = LM_LINE_SPEED_100MBPS; - } - else if (line_speed[index] == 10) { - - pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS; - } - else { - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->DisableAutoNeg = FALSE; - printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n", bcm5700_driver, index, line_speed[index]); - } - - } - -#endif /* LINUX_KERNEL_VERSION */ - - /* This is an unmanageable switch nic and will have link problems if - not set to auto - */ - if(pDevice->SubsystemVendorId==0x103c && pDevice->SubsystemId==0x3226) - { - if(pDevice->RequestedLineSpeed != LM_LINE_SPEED_AUTO) - { - printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n", - bcm5700_driver, index, line_speed[index]); - } - pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; - pDevice->DisableAutoNeg = FALSE; - } - -#if LINUX_KERNEL_VERSION < 0x0020609 - - pDevice->FlowControlCap = 0; - bcm5700_validate_param_range(pUmDevice, &rx_flow_control[index], - "rx_flow_control", 0, 1, 0); - if (rx_flow_control[index] != 0) { - pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - bcm5700_validate_param_range(pUmDevice, &tx_flow_control[index], - "tx_flow_control", 0, 1, 0); - if (tx_flow_control[index] != 0) { - pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; - } - bcm5700_validate_param_range(pUmDevice, &auto_flow_control[index], - "auto_flow_control", 0, 1, 0); - if (auto_flow_control[index] != 0) { - if (pDevice->DisableAutoNeg == FALSE) { - - pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE; - if ((tx_flow_control[index] == 0) && - (rx_flow_control[index] == 0)) { - - pDevice->FlowControlCap |= - LM_FLOW_CONTROL_TRANSMIT_PAUSE | - LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - } - } - - if (dev->mtu > 1500) { -#ifdef BCM_TSO - if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) && - (dev->features & NETIF_F_TSO)) { - dev->features &= ~NETIF_F_TSO; - printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name); - } -#endif - pDevice->RxMtu = dev->mtu + 14; - } - - if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) && - !(pDevice->Flags & BCM5788_FLAG)) { - pDevice->Flags |= USE_TAGGED_STATUS_FLAG; - pUmDevice->timer_interval = HZ; - if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) && - (pDevice->TbiFlags & ENABLE_TBI_FLAG)) { - pUmDevice->timer_interval = HZ/4; - } - } - else { - pUmDevice->timer_interval = HZ/10; - } - - bcm5700_validate_param_range(pUmDevice, &tx_pkt_desc_cnt[index], - "tx_pkt_desc_cnt", 1, MAX_TX_PACKET_DESC_COUNT-1, TX_DESC_CNT); - pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index]; - bcm5700_validate_param_range(pUmDevice, &rx_std_desc_cnt[index], - "rx_std_desc_cnt", 1, T3_STD_RCV_RCB_ENTRY_COUNT-1, - RX_DESC_CNT); - pDevice->RxStdDescCnt = rx_std_desc_cnt[index]; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - bcm5700_validate_param_range(pUmDevice, &rx_jumbo_desc_cnt[index], - "rx_jumbo_desc_cnt", 1, T3_JUMBO_RCV_RCB_ENTRY_COUNT-1, - JBO_DESC_CNT); - - if (mtu[index] <= 1514) - pDevice->RxJumboDescCnt = 0; - else if(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){ - pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index]; - } -#endif - -#ifdef BCM_INT_COAL - bcm5700_validate_param_range(pUmDevice, &adaptive_coalesce[index], - "adaptive_coalesce", 0, 1, 1); -#ifdef BCM_NAPI_RXPOLL - if (adaptive_coalesce[index]) { - printk(KERN_WARNING "%s-%d: adaptive_coalesce not used in NAPI mode\n", bcm5700_driver, index); - adaptive_coalesce[index] = 0; - - } -#endif - pUmDevice->adaptive_coalesce = adaptive_coalesce[index]; - if (!pUmDevice->adaptive_coalesce) { - bcm5700_validate_param_range(pUmDevice, - &rx_coalesce_ticks[index], "rx_coalesce_ticks", 0, - MAX_RX_COALESCING_TICKS, RX_COAL_TK); - if ((rx_coalesce_ticks[index] == 0) && - (rx_max_coalesce_frames[index] == 0)) { - - printk(KERN_WARNING "%s-%d: Conflicting rx_coalesce_ticks (0) and rx_max_coalesce_frames (0) parameters, using %d and %d respectively\n", - bcm5700_driver, index, RX_COAL_TK, RX_COAL_FM); - - rx_coalesce_ticks[index] = RX_COAL_TK; - rx_max_coalesce_frames[index] = RX_COAL_FM; - } - pDevice->RxCoalescingTicks = pUmDevice->rx_curr_coalesce_ticks = - rx_coalesce_ticks[index]; -#ifdef BCM_NAPI_RXPOLL - pDevice->RxCoalescingTicksDuringInt = rx_coalesce_ticks[index]; -#endif - - bcm5700_validate_param_range(pUmDevice, - &rx_max_coalesce_frames[index], - "rx_max_coalesce_frames", 0, - MAX_RX_MAX_COALESCED_FRAMES, RX_COAL_FM); - - pDevice->RxMaxCoalescedFrames = - pUmDevice->rx_curr_coalesce_frames = - rx_max_coalesce_frames[index]; -#ifdef BCM_NAPI_RXPOLL - pDevice->RxMaxCoalescedFramesDuringInt = - rx_max_coalesce_frames[index]; -#endif - - bcm5700_validate_param_range(pUmDevice, - &tx_coalesce_ticks[index], "tx_coalesce_ticks", 0, - MAX_TX_COALESCING_TICKS, TX_COAL_TK); - if ((tx_coalesce_ticks[index] == 0) && - (tx_max_coalesce_frames[index] == 0)) { - - printk(KERN_WARNING "%s-%d: Conflicting tx_coalesce_ticks (0) and tx_max_coalesce_frames (0) parameters, using %d and %d respectively\n", - bcm5700_driver, index, TX_COAL_TK, TX_COAL_FM); - - tx_coalesce_ticks[index] = TX_COAL_TK; - tx_max_coalesce_frames[index] = TX_COAL_FM; - } - pDevice->TxCoalescingTicks = tx_coalesce_ticks[index]; - bcm5700_validate_param_range(pUmDevice, - &tx_max_coalesce_frames[index], - "tx_max_coalesce_frames", 0, - MAX_TX_MAX_COALESCED_FRAMES, TX_COAL_FM); - pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index]; - pUmDevice->tx_curr_coalesce_frames = - pDevice->TxMaxCoalescedFrames; - - bcm5700_validate_param_range(pUmDevice, - &stats_coalesce_ticks[index], "stats_coalesce_ticks", - 0, MAX_STATS_COALESCING_TICKS, ST_COAL_TK); - if (adaptive_coalesce[index]) { - printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter set with with adaptive_coalesce parameter. Using adaptive_coalesce.\n", bcm5700_driver, index); - }else{ - if ((stats_coalesce_ticks[index] > 0) && - (stats_coalesce_ticks[index] < 100)) { - printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter (%u), using 100\n", bcm5700_driver, index, (unsigned int) stats_coalesce_ticks[index]); - stats_coalesce_ticks[index] = 100; - pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index]; - pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index]; - } - } - } - else { - pUmDevice->rx_curr_coalesce_frames = RX_COAL_FM; - pUmDevice->rx_curr_coalesce_ticks = RX_COAL_TK; - pUmDevice->tx_curr_coalesce_frames = TX_COAL_FM; - } -#endif - - if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) { - unsigned int tmpvar; - - tmpvar = pDevice->StatsCoalescingTicks / BCM_TIMER_GRANULARITY; - - /* - * If the result is zero, the request is too demanding. - */ - if (tmpvar == 0) { - tmpvar = 1; - } - - pDevice->StatsCoalescingTicks = tmpvar * BCM_TIMER_GRANULARITY; - - pUmDevice->statstimer_interval = tmpvar; - } - -#ifdef BCM_WOL - bcm5700_validate_param_range(pUmDevice, &enable_wol[index], - "enable_wol", 0, 1, 0); - if (enable_wol[index]) { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET; - pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET; - } -#endif -#ifdef INCLUDE_TBI_SUPPORT - if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { - if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) || - (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)) { - /* just poll since we have hardware autoneg. in 5704 */ - pDevice->TbiFlags |= TBI_PURE_POLLING_FLAG; - } - else { - pDevice->TbiFlags |= TBI_POLLING_INTR_FLAG; - } - } -#endif - bcm5700_validate_param_range(pUmDevice, &scatter_gather[index], - "scatter_gather", 0, 1, 1); - bcm5700_validate_param_range(pUmDevice, &tx_checksum[index], - "tx_checksum", 0, 1, 1); - bcm5700_validate_param_range(pUmDevice, &rx_checksum[index], - "rx_checksum", 0, 1, 1); - if (!(pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) { - if (tx_checksum[index] || rx_checksum[index]) { - - pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; - printk(KERN_WARNING "%s-%d: Checksum offload not available on this NIC\n", bcm5700_driver, index); - } - } - else { - if (rx_checksum[index]) { - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_RX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_RX_UDP_CHECKSUM; - } - if (tx_checksum[index]) { - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_TX_UDP_CHECKSUM; - pDevice->Flags |= NO_TX_PSEUDO_HDR_CSUM_FLAG; - } - } -#ifdef BCM_TSO - bcm5700_validate_param_range(pUmDevice, &enable_tso[index], - "enable_tso", 0, 1, 1); - - /* Always enable TSO firmware if supported */ - /* This way we can turn it on or off on the fly */ - if (pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION) - { - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_TCP_SEGMENTATION; - } - if (enable_tso[index] && - !(pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION)) - { - printk(KERN_WARNING "%s-%d: TSO not available on this NIC\n", bcm5700_driver, index); - } -#endif -#ifdef BCM_ASF - bcm5700_validate_param_range(pUmDevice, &vlan_tag_mode[index], - "vlan_strip_mode", 0, 2, 0); - pUmDevice->vlan_tag_mode = vlan_tag_mode[index]; -#else - pUmDevice->vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP; -#endif - -#endif /* LINUX_KERNEL_VERSION */ - -#ifdef BCM_NIC_SEND_BD - bcm5700_validate_param_range(pUmDevice, &nic_tx_bd[index], "nic_tx_bd", - 0, 1, 0); - if (nic_tx_bd[index]) - pDevice->Flags |= NIC_SEND_BD_FLAG; - if ((pDevice->Flags & ENABLE_PCIX_FIX_FLAG) || - (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) { - if (pDevice->Flags & NIC_SEND_BD_FLAG) { - pDevice->Flags &= ~NIC_SEND_BD_FLAG; - printk(KERN_WARNING "%s-%d: Nic Send BDs not available on this NIC or not possible on this system\n", bcm5700_driver, index); - } - } -#endif -#if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR) - bcm5700_validate_param_range(pUmDevice, &disable_msi[pUmDevice->index], - "disable_msi", 0, 1, 0); -#endif - - bcm5700_validate_param_range(pUmDevice, &delay_link[index], - "delay_link", 0, 1, 0); - - bcm5700_validate_param_range(pUmDevice, &disable_d3hot[index], - "disable_d3hot", 0, 1, 0); - if (disable_d3hot[index]) { - -#ifdef BCM_WOL - if (enable_wol[index]) { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; - pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE; - printk(KERN_WARNING "%s-%d: Wake-On-Lan disabled because D3Hot is disabled\n", bcm5700_driver, index); - } -#endif - pDevice->Flags |= DISABLE_D3HOT_FLAG; - } - - return LM_STATUS_SUCCESS; -} - -/* From include/proto/ethernet.h */ -#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ - -/* From include/proto/vlan.h */ -#define VLAN_PRI_MASK 7 /* 3 bits of priority */ -#define VLAN_PRI_SHIFT 13 - -/* Replace the priority in a vlan tag */ -#define UPD_VLANTAG_PRIO(tag, prio) do { \ - tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); \ - tag |= prio << VLAN_PRI_SHIFT; \ -} while (0) - -LM_STATUS -MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - struct sk_buff *skb; - int size; - int vlan_tag_size = 0; - uint16 dscp_prio; - - if (pDevice->ReceiveMask & LM_KEEP_VLAN_TAG) - vlan_tag_size = 4; - - while (1) { - pPacket = (PLM_PACKET) - QQ_PopHead(&pDevice->RxPacketReceivedQ.Container); - if (pPacket == 0) - break; - pUmPacket = (PUM_PACKET) pPacket; -#if !defined(NO_PCI_UNMAP) - pci_unmap_single(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[0]), - pPacket->u.Rx.RxBufferSize, - PCI_DMA_FROMDEVICE); -#endif - if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) || - ((size = pPacket->PacketSize) > - (pDevice->RxMtu + vlan_tag_size))) { - - /* reuse skb */ -#ifdef BCM_TASKLET - QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket); -#else - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); -#endif - pUmDevice->rx_misc_errors++; - continue; - } - skb = pUmPacket->skbuff; - skb_put(skb, size); - skb->pkt_type = 0; - -#ifdef HNDCTF - if (CTF_ENAB(pUmDevice->cih)) { - if (ctf_forward(pUmDevice->cih, skb, skb->dev) != BCME_ERROR) { - pUmDevice->dev->last_rx = jiffies; - pUmDevice->stats.rx_bytes += skb->len; - goto drop_rx; - } - - /* clear skipct flag before sending up */ - PKTCLRSKIPCT(pUmDevice->osh, skb); - } -#endif /* HNDCTF */ - - /* Extract priority from payload and put it in skb->priority */ - dscp_prio = 0; - if (pUmDevice->qos) { - uint rc; - - rc = pktsetprio(skb, TRUE); - if (rc & (PKTPRIO_VDSCP | PKTPRIO_DSCP)) - dscp_prio = rc & VLAN_PRI_MASK; - if (rc != 0) - B57_INFO(("pktsetprio returned 0x%x, skb->priority: %d\n", - rc, skb->priority)); - } - skb->protocol = eth_type_trans(skb, skb->dev); - if (size > pDevice->RxMtu) { - /* Make sure we have a valid VLAN tag */ - if (htons(skb->protocol) != ETHER_TYPE_8021Q) { - dev_kfree_skb_irq(skb); - pUmDevice->rx_misc_errors++; - goto drop_rx; - } - } - - pUmDevice->stats.rx_bytes += skb->len; - - if ((pPacket->Flags & RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD) && - (pDevice->TaskToOffload & - LM_TASK_OFFLOAD_RX_TCP_CHECKSUM)) { - if (pPacket->u.Rx.TcpUdpChecksum == 0xffff) { - - skb->ip_summed = CHECKSUM_UNNECESSARY; -#if TIGON3_DEBUG - pUmDevice->rx_good_chksum_count++; -#endif - } - else { - skb->ip_summed = CHECKSUM_NONE; - pUmDevice->rx_bad_chksum_count++; - } - } - else { - skb->ip_summed = CHECKSUM_NONE; - } -#ifdef NICE_SUPPORT - if( pUmDevice->nice_rx ) { - vlan_tag_t *vlan_tag; - - vlan_tag = (vlan_tag_t *) &skb->cb[0]; - if (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG) { - vlan_tag->signature = 0x7777; - vlan_tag->tag = pPacket->VlanTag; - /* Override vlan priority with dscp priority */ - if (dscp_prio) - UPD_VLANTAG_PRIO(vlan_tag->tag, dscp_prio); - } else { - vlan_tag->signature = 0; - } - pUmDevice->nice_rx(skb, pUmDevice->nice_ctx); - } else -#endif - { -#ifdef BCM_VLAN - if (pUmDevice->vlgrp && - (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG)) { - /* Override vlan priority with dscp priority */ - if (dscp_prio) - UPD_VLANTAG_PRIO(pPacket->VlanTag, dscp_prio); -#ifdef BCM_NAPI_RXPOLL - vlan_hwaccel_receive_skb(skb, pUmDevice->vlgrp, - pPacket->VlanTag); -#else - vlan_hwaccel_rx(skb, pUmDevice->vlgrp, - pPacket->VlanTag); -#endif - } else -#endif - { -#ifdef BCM_WL_EMULATOR - if(pDevice->wl_emulate_rx) { - /* bcmstats("emu recv %d %d"); */ - wlcemu_receive_skb(pDevice->wlc, skb); - /* bcmstats("emu recv end %d %d"); */ - } - else -#endif /* BCM_WL_EMULATOR */ - { -#ifdef BCM_NAPI_RXPOLL - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif - } - } - } - pUmDevice->dev->last_rx = jiffies; - -drop_rx: -#ifdef BCM_TASKLET - pUmPacket->skbuff = 0; - QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket); -#else -#ifdef BCM_WL_EMULATOR - skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2); -#else - skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR); -#endif /* BCM_WL_EMULATOR */ - if (skb == 0) { - pUmPacket->skbuff = 0; - QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket); - } - else { - pUmPacket->skbuff = skb; - skb->dev = pUmDevice->dev; -#ifndef BCM_WL_EMULATOR - skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align); -#endif - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); - } -#endif - } - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; - struct sk_buff *skb = pUmPacket->skbuff; - struct sk_buff *nskb; -#if !defined(NO_PCI_UNMAP) - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - - pci_unmap_single(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[0]), - pci_unmap_len(pUmPacket, map_len[0]), - PCI_DMA_TODEVICE); -#if MAX_SKB_FRAGS - { - int i; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - pci_unmap_page(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[i + 1]), - pci_unmap_len(pUmPacket, map_len[i + 1]), - PCI_DMA_TODEVICE); - } - } -#endif -#endif - if ((nskb = skb_copy(skb, GFP_ATOMIC))) { - pUmPacket->lm_packet.u.Tx.FragCount = 1; - dev_kfree_skb(skb); - pUmPacket->skbuff = nskb; - return LM_STATUS_SUCCESS; - } - dev_kfree_skb(skb); - pUmPacket->skbuff = 0; - return LM_STATUS_FAILURE; -} - -/* Returns 1 if not all buffers are allocated */ -STATIC int -replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max) -{ - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; - struct sk_buff *skb; - int queue_rx = 0; - int alloc_cnt = 0; - int ret = 0; - - while ((pUmPacket = (PUM_PACKET) - QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) { - pPacket = (PLM_PACKET) pUmPacket; - if (pUmPacket->skbuff) { - /* reuse an old skb */ - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); - queue_rx = 1; - continue; - } -#ifdef BCM_WL_EMULATOR - if ((skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2)) == 0) -#else - if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR)) == 0) -#endif /* BCM_WL_EMULATOR */ - { - QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container, - pPacket); - ret = 1; - break; - } - pUmPacket->skbuff = skb; - skb->dev = pUmDevice->dev; -#ifndef BCM_WL_EMULATOR - skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align); -#endif - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); - queue_rx = 1; - if (max > 0) { - alloc_cnt++; - if (alloc_cnt >= max) - break; - } - } - if (queue_rx || pDevice->QueueAgain) { - LM_QueueRxPackets(pDevice); - } - return ret; -} - -LM_STATUS -MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - struct sk_buff *skb; -#if !defined(NO_PCI_UNMAP) && MAX_SKB_FRAGS - int i; -#endif - - while (1) { - pPacket = (PLM_PACKET) - QQ_PopHead(&pDevice->TxPacketXmittedQ.Container); - if (pPacket == 0) - break; - pUmPacket = (PUM_PACKET) pPacket; - skb = pUmPacket->skbuff; -#if !defined(NO_PCI_UNMAP) - pci_unmap_single(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[0]), - pci_unmap_len(pUmPacket, map_len[0]), - PCI_DMA_TODEVICE); -#if MAX_SKB_FRAGS - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - pci_unmap_page(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[i + 1]), - pci_unmap_len(pUmPacket, map_len[i + 1]), - PCI_DMA_TODEVICE); - } -#endif -#endif - dev_kfree_skb_irq(skb); - pUmPacket->skbuff = 0; - QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket); - } - if (pUmDevice->tx_full) { - if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >= - (pDevice->TxPacketDescCnt >> 1)) { - - pUmDevice->tx_full = 0; - netif_wake_queue(pUmDevice->dev); - } - } - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - struct net_device *dev = pUmDevice->dev; - LM_FLOW_CONTROL flow_control; - int speed = 0; - - if (!pUmDevice->opened) - return LM_STATUS_SUCCESS; - - if (!pUmDevice->suspended) { - if (Status == LM_STATUS_LINK_DOWN) { - netif_carrier_off(dev); - } - else if (Status == LM_STATUS_LINK_ACTIVE) { - netif_carrier_on(dev); - } - } - - if (pUmDevice->delayed_link_ind > 0) { - pUmDevice->delayed_link_ind = 0; - if (Status == LM_STATUS_LINK_DOWN) { - B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name)); - } - else if (Status == LM_STATUS_LINK_ACTIVE) { - B57_INFO(("%s: %s NIC Link is UP, ", bcm5700_driver, dev->name)); - } - } - else { - if (Status == LM_STATUS_LINK_DOWN) { - B57_INFO(("%s: %s NIC Link is Down\n", bcm5700_driver, dev->name)); - } - else if (Status == LM_STATUS_LINK_ACTIVE) { - B57_INFO(("%s: %s NIC Link is Up, ", bcm5700_driver, dev->name)); - } - } - - if (Status == LM_STATUS_LINK_ACTIVE) { - if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) - speed = 1000; - else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) - speed = 100; - else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) - speed = 10; - - B57_INFO(("%d Mbps ", speed)); - - if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) - B57_INFO(("full duplex")); - else - B57_INFO(("half duplex")); - - flow_control = pDevice->FlowControl & - (LM_FLOW_CONTROL_RECEIVE_PAUSE | - LM_FLOW_CONTROL_TRANSMIT_PAUSE); - if (flow_control) { - if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) { - B57_INFO((", receive ")); - if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE) - B57_INFO(("& transmit ")); - } - else { - B57_INFO((", transmit ")); - } - B57_INFO(("flow control ON")); - } - B57_INFO(("\n")); - } - return LM_STATUS_SUCCESS; -} - -void -MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket) -{ -#if !defined(NO_PCI_UNMAP) - UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - UM_PACKET *pUmPacket = (UM_PACKET *) pPacket; - - if (!pUmPacket->skbuff) - return; - - pci_unmap_single(pUmDevice->pdev, - pci_unmap_addr(pUmPacket, map[0]), - pPacket->u.Rx.RxBufferSize, - PCI_DMA_FROMDEVICE); -#endif -} - -LM_STATUS -MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - PUM_PACKET pUmPacket; - struct sk_buff *skb; - - if (pPacket == 0) - return LM_STATUS_SUCCESS; - pUmPacket = (PUM_PACKET) pPacket; - if ((skb = pUmPacket->skbuff)) { - /* DMA address already unmapped */ - dev_kfree_skb(skb); - } - pUmPacket->skbuff = 0; - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec) -{ - current->state = TASK_INTERRUPTIBLE; - if (schedule_timeout(HZ * msec / 1000) != 0) { - return LM_STATUS_FAILURE; - } - if (signal_pending(current)) - return LM_STATUS_FAILURE; - - return LM_STATUS_SUCCESS; -} - -void -bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = (LM_DEVICE_BLOCK *) pUmDevice; - - bcm5700_intr_off(pUmDevice); - netif_carrier_off(pUmDevice->dev); -#ifdef BCM_TASKLET - tasklet_kill(&pUmDevice->tasklet); -#endif - bcm5700_poll_wait(pUmDevice); - - LM_Halt(pDevice); - - pDevice->InitDone = 0; - bcm5700_free_remaining_rx_bufs(pUmDevice); -} - -void -bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice) -{ - LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; - UM_PACKET *pUmPacket; - int cnt, i; - - cnt = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container); - for (i = 0; i < cnt; i++) { - if ((pUmPacket = - QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) - != 0) { - - MM_UnmapRxDma(pDevice, (LM_PACKET *) pUmPacket); - MM_FreeRxBuffer(pDevice, &pUmPacket->lm_packet); - QQ_PushTail(&pDevice->RxPacketFreeQ.Container, - pUmPacket); - } - } -} - -void -bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param, - char *param_name, int min, int max, int deflt) -{ - if (((unsigned int) *param < (unsigned int) min) || - ((unsigned int) *param > (unsigned int) max)) { - - printk(KERN_WARNING "%s-%d: Invalid %s parameter (%u), using %u\n", bcm5700_driver, pUmDevice->index, param_name, (unsigned int) *param, (unsigned int) deflt); - *param = deflt; - } -} - -struct net_device * -bcm5700_find_peer(struct net_device *dev) -{ - struct net_device *tmp_dev; - UM_DEVICE_BLOCK *pUmDevice, *pUmTmp; - LM_DEVICE_BLOCK *pDevice; - - tmp_dev = 0; - pUmDevice = (UM_DEVICE_BLOCK *) dev->priv; - pDevice = &pUmDevice->lm_dev; - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) { - tmp_dev = root_tigon3_dev; - while (tmp_dev) { - pUmTmp = (PUM_DEVICE_BLOCK) tmp_dev->priv; - if ((tmp_dev != dev) && - (pUmDevice->pdev->bus->number == - pUmTmp->pdev->bus->number) && - PCI_SLOT(pUmDevice->pdev->devfn) == - PCI_SLOT(pUmTmp->pdev->devfn)) { - - break; - } - tmp_dev = pUmTmp->next_module; - } - } - return tmp_dev; -} - -LM_DEVICE_BLOCK * -MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice) -{ - UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - struct net_device *dev = pUmDevice->dev; - struct net_device *peer_dev; - - peer_dev = bcm5700_find_peer(dev); - if (!peer_dev) - return 0; - return ((LM_DEVICE_BLOCK *) peer_dev->priv); -} - -int MM_FindCapability(LM_DEVICE_BLOCK *pDevice, int capability) -{ - UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - return (pci_find_capability(pUmDevice->pdev, capability)); -} - -#if defined(HAVE_POLL_CONTROLLER)||defined(CONFIG_NET_POLL_CONTROLLER) -STATIC void -poll_bcm5700(struct net_device *dev) -{ - UM_DEVICE_BLOCK *pUmDevice = dev->priv; - -#if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x020605) - if (netdump_mode) { - bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL); -#ifdef BCM_NAPI_RXPOLL - if (dev->poll_list.prev) { - int budget = 64; - - bcm5700_poll(dev, &budget); - } -#endif - } - else -#endif - { - disable_irq(pUmDevice->pdev->irq); - bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL); - enable_irq(pUmDevice->pdev->irq); - } -} -#endif diff --git a/release/src-rt/bcm57xx/linux/b57um.c b/release/src-rt/bcm57xx/linux/b57um.c old mode 100644 new mode 100755 index b0d7d0a5ce..f595977957 --- a/release/src-rt/bcm57xx/linux/b57um.c +++ b/release/src-rt/bcm57xx/linux/b57um.c @@ -10,7 +10,7 @@ /* */ /******************************************************************************/ -/* $Id: b57um.c,v 1.29.2.6 2010/02/21 20:06:36 Exp $ */ +/* $Id: b57um.c,v 1.34.10.1 2010-10-09 01:46:48 Exp $ */ char bcm5700_driver[] = "bcm5700"; char bcm5700_version[] = "8.3.14"; @@ -4329,6 +4329,68 @@ STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return 0; } + case SIOCSETGETVAR: + { + int ret = 0; + void *buffer = NULL; + bool get = FALSE, set = TRUE; + et_var_t var; + + if (set && mm_copy_from_user(&var, rq->ifr_data, sizeof(var))) + return -EFAULT; + + /* prepare buffer if any */ + if (var.buf) { + if (!var.set) + get = TRUE; + + if (!(buffer = (void *) MALLOC(SI_OSH, var.len))) { + B57_ERR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, + MALLOCED(SI_OSH))); + return -ENOMEM; + } + + if (mm_copy_from_user(buffer, var.buf, var.len)) { + MFREE(SI_OSH, buffer, var.len); + return -EFAULT; + } + } + + /* do var.cmd */ + switch (var.cmd) { + case IOV_ET_ROBO_DEVID: + { + uint *vecarg = (uint *)buffer; + robo_info_t *robo = (robo_info_t *)pUmDevice->robo; + + if (((pDevice->Flags & ROBO_SWITCH_FLAG) == 0) || + (robo == NULL)) { + ret = -ENXIO; + break; + } + + /* get robo device id */ + *vecarg = robo->devid; + + if (mm_copy_to_user(var.buf, buffer, var.len)) { + ret = -EFAULT; + break; + } + + break; + } + + default: + ret = -EOPNOTSUPP; + break; + } + + if (buffer) + MFREE(SI_OSH, buffer, var.len); + + return ret; + } + case SIOCSETCSETMSGLEVEL: if (mm_copy_from_user(&value, rq->ifr_data, sizeof(value))) return -EFAULT; diff --git a/release/src-rt/bcmcrypto/Makefile b/release/src-rt/bcmcrypto/Makefile new file mode 100755 index 0000000000..4eef5d0107 --- /dev/null +++ b/release/src-rt/bcmcrypto/Makefile @@ -0,0 +1,69 @@ +# +# Assorted cryptographic algorithms +# +# Copyright (C) 2002 Broadcom Corporation +# +# $Id: Makefile,v 1.30.10.1 2010-05-28 15:25:49 Exp $ +# + +SRCBASE := .. + +CC := gcc +CFLAGS += -I. -I$(SRCBASE)/include -Wall +CFLAGS += -g -DDEBUG -ffunction-sections +#CFLAGS += -O2 +CFLAGS += -Wall -Werror + +#CC := cl +#CFLAGS += -I. -I../include -Ic:/tools/msdev/2600ddk/inc/crt +#LDFLAGS += -link -LIBPATH:c:/tools/msdev/2600ddk/lib/wxp/i386 + +PROGS := aes aeskeywrap des dh passhash prf rc4 sha1 tkhash tkhash_shared_sbox sha256 + + + +all: $(PROGS) + +clean: + rm -f *.o *.obj $(PROGS) *.exe + +AESFLAGS := -DBCMAES_TEST -DBCMAES_TEST_STANDALONE -DBCMAES_GENTABLE +aes: aes.c rijndael-alg-fst.c + $(CC) $(CFLAGS) $(AESFLAGS) -o $@ $^ $(LDFLAGS) + +aeskeywrap: aeskeywrap.c aes.c rijndael-alg-fst.c + $(CC) $(CFLAGS) -DBCMAESKEYWRAP_TEST -o $@ $^ $(LDFLAGS) + + +des: des.c + $(CC) $(CFLAGS) -DDES_TEST_STANDALONE -o $@ $^ $(LDFLAGS) + +passhash: passhash.c sha1.c prf.c + $(CC) $(CFLAGS) -DBCMPASSHASH_TEST -o $@ $^ $(LDFLAGS) + +prf: prf.c hmac.c sha1.c md5.c + $(CC) $(CFLAGS) -DBCMPRF_TEST -DBCMCCX -o $@ $^ $(LDFLAGS) + +rc4: rc4.c + $(CC) $(CFLAGS) -DBCMRC4_TEST -o $@ $^ $(LDFLAGS) + +sha1: sha1.c + $(CC) $(CFLAGS) -DBCMSHA1_TEST -o $@ $^ $(LDFLAGS) + +sha256: sha256.c + $(CC) $(CFLAGS) -DBCMSHA256_TEST -o $@ $^ $(LDFLAGS) + + +tkhash: tkhash.c + $(CC) $(CFLAGS) -DBCMTKHASH_TEST -o $@ $^ $(LDFLAGS) + +tkhash_shared_sbox: tkhash.c rijndael-alg-fst.c + $(CC) $(CFLAGS) -DBCMTKHASH_TEST -DSHARE_RIJNDAEL_SBOX -o $@ $^ $(LDFLAGS) + +dh: dh.c bn.c random.c + $(CC) $(CFLAGS) -m32 -DBCMDH_TEST -o $@ $^ $(LDFLAGS) + +install: + install -d $(INSTALLDIR)/usr/sbin + install $(PROGS) $(INSTALLDIR)/usr/sbin + $(STRIP) $(foreach file,$(PROGS),$(INSTALLDIR)/usr/sbin/$(file)) diff --git a/release/src-rt/bcmcrypto/aes.c b/release/src-rt/bcmcrypto/aes.c new file mode 100755 index 0000000000..1d721706d5 --- /dev/null +++ b/release/src-rt/bcmcrypto/aes.c @@ -0,0 +1,1198 @@ +/* + * aes.c + * AES encrypt/decrypt wrapper functions used around Rijndael reference + * implementation + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: aes.c,v 1.34.10.1 2010-05-28 15:25:49 Exp $ + */ + +#include +#ifdef BCMDRIVER +#include +#else +#include /* for size_t */ +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, size_t len); +extern int bcmp(const void *b1, const void *b2, size_t len); +extern void bzero(void *b, size_t len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif +#endif /* BCMDRIVER */ +#include +#include +#include +#include +#include + +#ifdef BCMAES_TEST +#include + +#define dbg(args) printf args + +void +pinter(const char *label, const uint8 *A, const size_t il, const uint8 *R) +{ + int k; + printf("%s", label); + for (k = 0; k < AES_BLOCK_SZ; k++) + printf("%02X", A[k]); + printf(" "); + for (k = 0; k < il; k++) { + printf("%02X", R[k]); + if (!((k + 1) % AES_BLOCK_SZ)) + printf(" "); + } + printf("\n"); +} + +void +pres(const char *label, const size_t len, const uint8 *data) +{ + int k; + printf("%s\n", label); + for (k = 0; k < len; k++) { + printf("%02x ", data[k]); + if (!((k + 1) % AES_BLOCK_SZ)) + printf("\n"); + } + printf("\n"); +} + +#ifdef BCMAES_GENTABLE +void +ptable(const char *tablename, const uint32 *table) +{ + int k; + printf("static const uint32 %s[256] = {\n ", tablename); + for (k = 0; k < 256; k++) { + printf("0x%08xU", table[k]); + if ((k+1) % 4) + printf(", "); + else + if (k != 255) + printf(",\n "); + else + printf("\n"); + } + printf("};\n"); +} +#endif /* BCMAES_GENTABLE */ + +#else +#define dbg(args) +#define pinter(label, A, il, R) +#define pres(label, len, data) +#endif /* BCMAES_TEST */ + +/* +* ptxt - plain text +* ctxt - cipher text +*/ + +/* Perform AES block encryption, including key schedule setup */ +void +BCMROMFN(aes_encrypt)(const size_t kl, const uint8 *K, const uint8 *ptxt, uint8 *ctxt) +{ + uint32 rk[4 * (AES_MAXROUNDS + 1)]; + rijndaelKeySetupEnc(rk, K, (int)AES_KEY_BITLEN(kl)); + rijndaelEncrypt(rk, (int)AES_ROUNDS(kl), ptxt, ctxt); +} + +/* Perform AES block decryption, including key schedule setup */ +void +BCMROMFN(aes_decrypt)(const size_t kl, const uint8 *K, const uint8 *ctxt, uint8 *ptxt) +{ + uint32 rk[4 * (AES_MAXROUNDS + 1)]; + rijndaelKeySetupDec(rk, K, (int)AES_KEY_BITLEN(kl)); + rijndaelDecrypt(rk, (int)AES_ROUNDS(kl), ctxt, ptxt); +} + +/* AES-CBC mode encryption algorithm + * - handle partial blocks with padding of type as above + * - assumes nonce is ready to use as-is (i.e. any + * encryption/randomization of nonce/IV is handled by the caller) + * - ptxt and ctxt can point to the same location + * - returns -1 on error or final length of output + */ + + +int +BCMROMFN(aes_cbc_encrypt_pad)(uint32 *rk, + const size_t key_len, + const uint8 *nonce, + const size_t data_len, + const uint8 *ptxt, + uint8 *ctxt, + uint8 padd_type) +{ + + uint8 tmp[AES_BLOCK_SZ]; + uint32 encrypt_len = 0; + uint32 j; + + /* First block get XORed with nonce/IV */ + const unsigned char *iv = nonce; + unsigned char *crypt_data = ctxt; + const unsigned char *plain_data = ptxt; + uint32 remaining = (uint32)data_len; + + while (remaining >= AES_BLOCK_SZ) + { + xor_128bit_block(iv, plain_data, tmp); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, crypt_data); + remaining -= AES_BLOCK_SZ; + iv = crypt_data; + crypt_data += AES_BLOCK_SZ; + plain_data += AES_BLOCK_SZ; + encrypt_len += AES_BLOCK_SZ; + } + + if (padd_type == NO_PADDING) + return encrypt_len; + + if (remaining) { + for (j = 0; j < remaining; j++) + { + tmp[j] = plain_data[j] ^ iv[j]; + } + } + switch (padd_type) + { + case PAD_LEN_PADDING: + for (j = remaining; j < AES_BLOCK_SZ; j++) { + tmp[j] = (AES_BLOCK_SZ - remaining) ^ iv[j]; + } + break; + default: + return -1; + } + + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, crypt_data); + encrypt_len += AES_BLOCK_SZ; + + return (encrypt_len); +} + +/* AES-CBC mode encryption algorithm + * - does not handle partial blocks + * - assumes nonce is ready to use as-is (i.e. any + * encryption/randomization of nonce/IV is handled by the caller) + * - ptxt and ctxt can point to the same location + * - returns -1 on error + */ + +int +BCMROMFN(aes_cbc_encrypt)(uint32 *rk, + const size_t key_len, + const uint8 *nonce, + const size_t data_len, + const uint8 *ptxt, + uint8 *ctxt) +{ + if (data_len % AES_BLOCK_SZ) return (-1); + if (data_len < AES_BLOCK_SZ) return (-1); + + return aes_cbc_encrypt_pad(rk, key_len, nonce, data_len, ptxt, ctxt, NO_PADDING); +} + + +/* AES-CBC mode decryption algorithm + * - handle partial plaintext blocks with padding + * - ptxt and ctxt can point to the same location + * - returns -1 on error + */ +int +BCMROMFN(aes_cbc_decrypt_pad)(uint32 *rk, + const size_t key_len, + const uint8 *nonce, + const size_t data_len, + const uint8 *ctxt, + uint8 *ptxt, + uint8 padd_type) +{ + uint8 tmp[AES_BLOCK_SZ]; + uint32 remaining = (uint32)data_len; + /* First block get XORed with nonce/IV */ + const unsigned char *iv = nonce; + const unsigned char *crypt_data = ctxt; + uint32 plaintext_len = 0; + unsigned char *plain_data = ptxt; + + if (data_len % AES_BLOCK_SZ) return (-1); + if (data_len < AES_BLOCK_SZ) return (-1); + + while (remaining >= AES_BLOCK_SZ) + { + aes_block_decrypt((int)AES_ROUNDS(key_len), rk, crypt_data, tmp); + xor_128bit_block(tmp, iv, plain_data); + remaining -= AES_BLOCK_SZ; + iv = crypt_data; + crypt_data += AES_BLOCK_SZ; + plain_data += AES_BLOCK_SZ; + plaintext_len += AES_BLOCK_SZ; + } + if (padd_type == PAD_LEN_PADDING) + plaintext_len -= ptxt[plaintext_len -1]; + return (plaintext_len); +} + +int +BCMROMFN(aes_cbc_decrypt)(uint32 *rk, + const size_t key_len, + const uint8 *nonce, + const size_t data_len, + const uint8 *ctxt, + uint8 *ptxt) +{ + + return aes_cbc_decrypt_pad(rk, key_len, nonce, data_len, ctxt, ptxt, NO_PADDING); + +} + + +/* AES-CTR mode encryption/decryption algorithm + * - max data_len is (AES_BLOCK_SZ * 2^16) + * - nonce must be AES_BLOCK_SZ bytes + * - assumes nonce is ready to use as-is (i.e. any + * encryption/randomization of nonce/IV is handled by the caller) + * - ptxt and ctxt can point to the same location + * - returns -1 on error + */ +int +BCMROMFN(aes_ctr_crypt)(unsigned int *rk, + const size_t key_len, + const uint8 *nonce, + const size_t data_len, + const uint8 *ptxt, + uint8 *ctxt) +{ + size_t k; + uint8 tmp[AES_BLOCK_SZ], ctr[AES_BLOCK_SZ]; + + if (data_len > (AES_BLOCK_SZ * AES_CTR_MAXBLOCKS)) return (-1); + + bcopy(nonce, ctr, AES_BLOCK_SZ); + + for (k = 0; k < (data_len / AES_BLOCK_SZ); k++) { + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, ctr, tmp); + xor_128bit_block(ptxt, tmp, ctxt); + ctr[AES_BLOCK_SZ-1]++; + if (!ctr[AES_BLOCK_SZ - 1]) ctr[AES_BLOCK_SZ - 2]++; + ptxt += AES_BLOCK_SZ; + ctxt += AES_BLOCK_SZ; + } + /* handle partial block */ + if (data_len%AES_BLOCK_SZ) { + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, ctr, tmp); + for (k = 0; k < (data_len % AES_BLOCK_SZ); k++) + ctxt[k] = ptxt[k] ^ tmp[k]; + } + + return (0); +} + + +/* AES-CCM mode MAC calculation + * - computes AES_CCM_AUTH_LEN MAC + * - nonce must be AES_CCM_NONCE_LEN bytes + * - returns -1 on error + */ + +int +BCMROMFN(aes_ccm_mac)(unsigned int *rk, + const size_t key_len, + const uint8 *nonce, + const size_t aad_len, + const uint8 *aad, + const size_t data_len, + const uint8 *ptxt, + uint8 *mac) +{ + uint8 B_0[AES_BLOCK_SZ], X[AES_BLOCK_SZ]; + size_t j, k; + + if (aad_len > AES_CCM_AAD_MAX_LEN) return (-1); + + pres("aes_ccm_mac: nonce:", AES_CCM_NONCE_LEN, nonce); + pres("aes_ccm_mac: aad:", aad_len, aad); + pres("aes_ccm_mac: input:", data_len, ptxt); + + /* B_0 = Flags || Nonce || l(m) */ + B_0[0] = AES_CCM_AUTH_FLAGS; + if (aad_len) + B_0[0] |= AES_CCM_AUTH_AAD_FLAG; + bcopy(nonce, &B_0[1], AES_CCM_NONCE_LEN); + B_0[AES_BLOCK_SZ - 2] = (uint8)(data_len >> 8) & 0xff; + B_0[AES_BLOCK_SZ - 1] = (uint8)(data_len & 0xff); + + /* X_1 := E( K, B_0 ) */ + pres("aes_ccm_mac: CBC IV in:", AES_BLOCK_SZ, B_0); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, B_0, X); + pres("aes_ccm_mac: CBC IV out:", AES_BLOCK_SZ, X); + + /* X_i + 1 := E( K, X_i XOR B_i ) for i = 1, ..., n */ + + /* first the AAD */ + if (aad_len) { + pres("aes_ccm_mac: aad:", aad_len, aad); + X[0] ^= (aad_len >> 8) & 0xff; + X[1] ^= aad_len & 0xff; + k = 2; + j = aad_len; + while (j--) { + X[k] ^= *aad++; + k++; + if (k == AES_BLOCK_SZ) { + pres("aes_ccm_mac: After xor (full block aad):", AES_BLOCK_SZ, X); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); + pres("aes_ccm_mac: After AES (full block aad):", AES_BLOCK_SZ, X); + k = 0; + } + } + /* handle partial last block */ + if (k % AES_BLOCK_SZ) { + pres("aes_ccm_mac: After xor (partial block aad):", AES_BLOCK_SZ, X); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); + pres("aes_ccm_mac: After AES (partial block aad):", AES_BLOCK_SZ, X); + } + } + + /* then the message data */ + for (k = 0; k < (data_len / AES_BLOCK_SZ); k++) { + xor_128bit_block(X, ptxt, X); + pres("aes_ccm_mac: After xor (full block data):", AES_BLOCK_SZ, X); + ptxt += AES_BLOCK_SZ; + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); + pres("aes_ccm_mac: After AES (full block data):", AES_BLOCK_SZ, X); + } + /* last block may be partial, padding is implicit in this xor */ + for (k = 0; k < (data_len % AES_BLOCK_SZ); k++) + X[k] ^= *ptxt++; + if (data_len % AES_BLOCK_SZ) { + pres("aes_ccm_mac: After xor (final block data):", AES_BLOCK_SZ, X); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); + pres("aes_ccm_mac: After AES (final block data):", AES_BLOCK_SZ, X); + } + + /* T := first-M-bytes( X_n+1 ) */ + bcopy(X, mac, AES_CCM_AUTH_LEN); + pres("aes_ccm_mac: MAC:", AES_CCM_AUTH_LEN, mac); + + return (0); +} + +/* AES-CCM mode encryption + * - computes AES_CCM_AUTH_LEN MAC and then encrypts ptxt and MAC + * - nonce must be AES_CCM_NONCE_LEN bytes + * - ctxt must have sufficient tailroom for CCM MAC + * - ptxt and ctxt can point to the same location + * - returns -1 on error + */ + +int +BCMROMFN(aes_ccm_encrypt)(unsigned int *rk, + const size_t key_len, + const uint8 *nonce, + const size_t aad_len, + const uint8 *aad, + const size_t data_len, + const uint8 *ptxt, + uint8 *ctxt, + uint8 *mac) +{ + uint8 A[AES_BLOCK_SZ], X[AES_BLOCK_SZ]; + + /* initialize counter */ + A[0] = AES_CCM_CRYPT_FLAGS; + bcopy(nonce, &A[1], AES_CCM_NONCE_LEN); + A[AES_BLOCK_SZ-2] = 0; + A[AES_BLOCK_SZ-1] = 0; + pres("aes_ccm_encrypt: initial counter:", AES_BLOCK_SZ, A); + + /* calculate and encrypt MAC */ + if (aes_ccm_mac(rk, key_len, nonce, aad_len, aad, data_len, ptxt, X)) + return (-1); + pres("aes_ccm_encrypt: MAC:", AES_CCM_AUTH_LEN, X); + if (aes_ctr_crypt(rk, key_len, A, AES_CCM_AUTH_LEN, X, X)) + return (-1); + pres("aes_ccm_encrypt: encrypted MAC:", AES_CCM_AUTH_LEN, X); + bcopy(X, mac, AES_CCM_AUTH_LEN); + + /* encrypt data */ + A[AES_BLOCK_SZ - 1] = 1; + if (aes_ctr_crypt(rk, key_len, A, data_len, ptxt, ctxt)) + return (-1); + pres("aes_ccm_encrypt: encrypted data:", data_len, ctxt); + + return (0); +} + +/* AES-CCM mode decryption + * - decrypts ctxt, then computes AES_CCM_AUTH_LEN MAC and checks it against + * then decrypted MAC + * - the decrypted MAC is included in ptxt + * - nonce must be AES_CCM_NONCE_LEN bytes + * - ptxt and ctxt can point to the same location + * - returns -1 on error + */ + +int +BCMROMFN(aes_ccm_decrypt)(unsigned int *rk, + const size_t key_len, + const uint8 *nonce, + const size_t aad_len, + const uint8 *aad, + const size_t data_len, + const uint8 *ctxt, + uint8 *ptxt) +{ + uint8 A[AES_BLOCK_SZ], X[AES_BLOCK_SZ]; + + /* initialize counter */ + A[0] = AES_CCM_CRYPT_FLAGS; + bcopy(nonce, &A[1], AES_CCM_NONCE_LEN); + A[AES_BLOCK_SZ - 2] = 0; + A[AES_BLOCK_SZ - 1] = 1; + pres("aes_ccm_decrypt: initial counter:", AES_BLOCK_SZ, A); + + /* decrypt data */ + if (aes_ctr_crypt(rk, key_len, A, data_len-AES_CCM_AUTH_LEN, ctxt, ptxt)) + return (-1); + pres("aes_ccm_decrypt: decrypted data:", data_len-AES_CCM_AUTH_LEN, ptxt); + + /* decrypt MAC */ + A[AES_BLOCK_SZ - 2] = 0; + A[AES_BLOCK_SZ - 1] = 0; + if (aes_ctr_crypt(rk, key_len, A, AES_CCM_AUTH_LEN, + ctxt+data_len-AES_CCM_AUTH_LEN, ptxt + data_len - AES_CCM_AUTH_LEN)) + return (-1); + pres("aes_ccm_decrypt: decrypted MAC:", AES_CCM_AUTH_LEN, + ptxt + data_len - AES_CCM_AUTH_LEN); + + /* calculate MAC */ + if (aes_ccm_mac(rk, key_len, nonce, aad_len, aad, + data_len - AES_CCM_AUTH_LEN, ptxt, X)) + return (-1); + pres("aes_ccm_decrypt: MAC:", AES_CCM_AUTH_LEN, X); + if (bcmp(X, ptxt + data_len - AES_CCM_AUTH_LEN, AES_CCM_AUTH_LEN) != 0) + return (-1); + + return (0); +} + +/* AES-CCMP mode encryption algorithm + * - packet buffer should be an 802.11 MPDU, starting with Frame Control, + * and including the CCMP extended IV + * - encrypts in-place + * - packet buffer must have sufficient tailroom for CCMP MAC + * - returns -1 on error + */ + + +int +BCMROMFN(aes_ccmp_encrypt)(unsigned int *rk, + const size_t key_len, + const size_t data_len, + uint8 *p, + bool legacy, + uint8 nonce_1st_byte) +{ + uint8 nonce[AES_CCMP_NONCE_LEN], aad[AES_CCMP_AAD_MAX_LEN]; + struct dot11_header *h = (struct dot11_header*) p; + uint la, lh; + int status = 0; + + aes_ccmp_cal_params(h, legacy, nonce_1st_byte, nonce, aad, &la, &lh); + + pres("aes_ccmp_encrypt: aad:", la, aad); + + /* + * MData: + * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2 + * m || pad(m) + */ + + status = aes_ccm_encrypt(rk, key_len, nonce, la, aad, + data_len - lh, p + lh, p + lh, p + data_len); + + pres("aes_ccmp_encrypt: Encrypted packet with MAC:", + data_len+AES_CCMP_AUTH_LEN, p); + + if (status) return (AES_CCMP_ENCRYPT_ERROR); + else return (AES_CCMP_ENCRYPT_SUCCESS); +} + +int +BCMROMFN(aes_ccmp_decrypt)(unsigned int *rk, + const size_t key_len, + const size_t data_len, + uint8 *p, + bool legacy, + uint8 nonce_1st_byte) +{ + uint8 nonce[AES_CCMP_NONCE_LEN], aad[AES_CCMP_AAD_MAX_LEN]; + struct dot11_header *h = (struct dot11_header *)p; + uint la, lh; + int status = 0; + + aes_ccmp_cal_params(h, legacy, nonce_1st_byte, nonce, aad, &la, &lh); + + pres("aes_ccmp_decrypt: aad:", la, aad); + + /* + * MData: + * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2 + * m || pad(m) + */ + + status = aes_ccm_decrypt(rk, key_len, nonce, la, aad, + data_len - lh, p + lh, p + lh); + + pres("aes_ccmp_decrypt: Decrypted packet with MAC:", data_len, p); + + if (status) return (AES_CCMP_DECRYPT_MIC_FAIL); + else return (AES_CCMP_DECRYPT_SUCCESS); +} + +void +BCMROMFN(aes_ccmp_cal_params)(struct dot11_header *h, bool legacy, + uint8 nonce_1st_byte, uint8 *nonce, uint8 *aad, uint *la, uint *lh) +{ + uint8 *iv_data; + uint16 fc, subtype; + uint16 seq, qc = 0; + uint addlen = 0; + bool wds, qos; + + bzero(nonce, AES_CCMP_NONCE_LEN); + bzero(aad, AES_CCMP_AAD_MAX_LEN); + + fc = ltoh16(h->fc); + subtype = (fc & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT; + wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS)); + /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */ + qos = (FC_TYPE(fc) == FC_TYPE_DATA) && (subtype & FC_SUBTYPE_QOS_DATA); + + if (qos) { + qc = ltoh16(*((uint16 *)((uchar *)h + + (wds ? DOT11_A4_HDR_LEN : DOT11_A3_HDR_LEN)))); + } + + if (wds) { + dbg(("aes_ccmp_cal_params: A4 present\n")); + addlen += ETHER_ADDR_LEN; + } + if (qos) { + dbg(("aes_ccmp_cal_params: QC present\n")); + addlen += DOT11_QOS_LEN; + } + + /* length of MPDU header, including IV */ + *lh = DOT11_A3_HDR_LEN + DOT11_IV_AES_CCM_LEN + addlen; + /* length of AAD */ + *la = AES_CCMP_AAD_MIN_LEN + addlen; + /* pointer to IV */ + iv_data = (uint8 *)h + DOT11_A3_HDR_LEN + addlen; + + *nonce++ = nonce_1st_byte; + + bcopy((uchar *)&h->a2, nonce, ETHER_ADDR_LEN); + nonce += ETHER_ADDR_LEN; + + /* PN[5] */ + *nonce++ = iv_data[7]; + /* PN[4] */ + *nonce++ = iv_data[6]; + /* PN[3] */ + *nonce++ = iv_data[5]; + /* PN[2] */ + *nonce++ = iv_data[4]; + /* PN[1] */ + *nonce++ = iv_data[1]; + /* PN[0] */ + *nonce++ = iv_data[0]; + + pres("aes_ccmp_cal_params: nonce:", AES_CCM_NONCE_LEN, nonce - AES_CCM_NONCE_LEN); + + /* B1..B2 = l(aad) || aad || pad(aad) */ + /* aad: maskedFC || A1 || A2 || A3 || maskedSC || A4 || maskedQC */ + + if (!legacy) { +#ifdef MFP + /* For a management frame, don't mask the the subtype bits */ + if (nonce_1st_byte & AES_CCMP_NF_MANAGEMENT) + fc &= (FC_SUBTYPE_MASK | AES_CCMP_FC_MASK); + else +#endif /* MFP */ + fc &= AES_CCMP_FC_MASK; + } else { + /* 802.11i Draft 3 inconsistencies: + * Clause 8.3.4.4.3: "FC ­ MPDU Frame Control field, with Retry bit masked + * to zero." (8.3.4.4.3). + * Figure 29: "FC ­ MPDU Frame Control field, with Retry, MoreData, CF-ACK, + * CF-POLL bits masked to zero." + * F.10.4.1: "FC ­ MPDU Frame Control field, with Retry, MoreData, + * PwrMgmt bits masked to zero." + */ + + /* Our implementation: match 8.3.4.4.3 */ + fc &= AES_CCMP_LEGACY_FC_MASK; + } + *aad++ = (uint8)(fc & 0xff); + *aad++ = (uint8)((fc >> 8) & 0xff); + + bcopy((uchar *)&h->a1, aad, 3*ETHER_ADDR_LEN); + aad += 3*ETHER_ADDR_LEN; + + seq = ltoh16(h->seq); + if (!legacy) { + seq &= AES_CCMP_SEQ_MASK; + } else { + seq &= AES_CCMP_LEGACY_SEQ_MASK; + } + + *aad++ = (uint8)(seq & 0xff); + *aad++ = (uint8)((seq >> 8) & 0xff); + + if (wds) { + bcopy((uchar *)&h->a4, aad, ETHER_ADDR_LEN); + aad += ETHER_ADDR_LEN; + } + if (qos) { + if (!legacy) { + /* 802.11i Draft 7.0 inconsistencies: + * Clause 8.3.3.3.2: "QC ­ The Quality of Service Control, a + * two-octet field that includes the MSDU priority, reserved + * for future use." + * I.7.4: TID portion of QoS + */ + + /* Our implementation: match the test vectors */ + qc &= AES_CCMP_QOS_MASK; + *aad++ = (uint8)(qc & 0xff); + *aad++ = (uint8)((qc >> 8) & 0xff); + } else { + /* 802.11i Draft 3.0 inconsistencies: */ + /* Clause 8.3.4.4.3: "QC ­ The QoS Control, if present." */ + /* Figure 30: "QC ­ The QoS TC from QoS Control, if present." */ + /* F.10.4.1: "QC ­ The QoS TC from QoS Control, if present." */ + + /* Our implementation: Match clause 8.3.4.4.3 */ + qc &= AES_CCMP_LEGACY_QOS_MASK; + *aad++ = (uint8)(qc & 0xff); + *aad++ = (uint8)((qc >> 8) & 0xff); + } + } +} + +#if defined(WLFBT) +/* 128-bit long string of zeros */ +static uint8 Z128[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* CMAC Subkey generation polynomial for 128-bit blocks */ +static uint8 R128[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 +}; + +/* AES-CMAC subkey generation + * - computes subkeys K1 and K2 of length AES_BLOCK_SZ + */ +void +aes_cmac_gen_subkeys(const size_t kl, const uint8 *K, uint8 *K1, uint8 *K2) +{ + uint8 L[AES_BLOCK_SZ]; + uint8 high, low; + int i; + + /* L = CIPHK(0b) */ + aes_encrypt(kl, K, Z128, L); + pres("Key", kl, K); + pres("CIPHK", AES_BLOCK_SZ, L); + + /* If MSB1(L) = 0, then K1 = L << 1 */ + /* Else K1 = (L << 1) ⊕ Rb */ + high = 0; + for (i = AES_BLOCK_SZ-1; i >= 0; i--) { + low = L[i] << 1; + K1[i] = low | high; + high = (L[i] & 0x80) >> 7; + } + if ((L[0] & 0x80) != 0) xor_128bit_block(K1, R128, K1); + pres("K1", AES_BLOCK_SZ, K1); + + /* If MSB1(K1) = 0, then K2 = K1 << 1 */ + /* Else K2 = (K1 << 1) ⊕ Rb */ + high = 0; + for (i = AES_BLOCK_SZ-1; i >= 0; i--) { + low = K1[i] << 1; + K2[i] = low | high; + high = (K1[i] & 0x80) >> 7; + } + if ((K1[0] & 0x80) != 0) xor_128bit_block(K2, R128, K2); + pres("K2", AES_BLOCK_SZ, K2); + + return; +} + +/* AES-CMAC mode calculation + * - computes AES_CMAC_AUTH_LEN MAC + * - operates on complete bytes only (i.e. data_len is in bytes) + */ + +void +aes_cmac(const size_t key_len, const uint8* K, + const uint8 *K1, const uint8 *K2, + const size_t data_len, + const uint8 *ptxt, + uint8 *mac) +{ + uint n, pblen, i; + uint8 Mn[AES_BLOCK_SZ], tmp[AES_BLOCK_SZ], C[AES_BLOCK_SZ]; + uint32 rk[4 * (AES_MAXROUNDS + 1)]; + + /* If Mlen = 0, let n = 1; else, let n = ⎡Mlen/b⎤ */ + if (data_len == 0) + n = 1; + else + n = (data_len + AES_BLOCK_SZ - 1)/AES_BLOCK_SZ; + + /* Let M1, M2, ... , Mn-1, Mn* denote the unique sequence of bit + strings such that M = M1 || M2 || ... || Mn-1 || Mn*, where M1, + M2,..., Mn-1 are complete blocks. If Mn* is a complete block, let + Mn = K1 ⊕ Mn*; else, let Mn = K2 ⊕ (Mn*||10j), where j = nb-Mlen-1 + */ + + if (data_len == (n * AES_BLOCK_SZ)) { + /* Mn* is a complete block */ + xor_128bit_block(K1, &(ptxt[(n-1)*AES_BLOCK_SZ]), Mn); + } else { + /* Mn* is a partial block, pad with 0s and use K2 */ + pblen = data_len - ((n-1)*AES_BLOCK_SZ); + for (i = 0; i < pblen; i++) Mn[i] = ptxt[((n-1)*AES_BLOCK_SZ) + i]; + Mn[pblen] = 0x80; + for (i = pblen+1; i < AES_BLOCK_SZ; i++) Mn[i] = 0; + xor_128bit_block(K2, Mn, Mn); + } + + /* Let C0 = 0b */ + bzero(C, AES_BLOCK_SZ); + + /* For i = 1 to n, let Ci = CIPHK(Ci-1 ⊕ Mi) */ + rijndaelKeySetupEnc(rk, K, (int)AES_KEY_BITLEN(key_len)); + for (i = 1; i < n; i++) { + xor_128bit_block(C, &(ptxt[(i-1)*AES_BLOCK_SZ]), tmp); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, C); + } + xor_128bit_block(C, Mn, tmp); + aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, C); + + /* Let T = MSBTlen(Cn) */ + bcopy(C, mac, AES_CMAC_AUTH_LEN); + + return; +} + + +void +aes_cmac_calc(const uint8 *data, const size_t data_length, const uint8 *mic_key, + const size_t key_len, uint8 *mic) +{ + uint8 K1[AES_BLOCK_SZ], K2[AES_BLOCK_SZ]; + + aes_cmac_gen_subkeys(key_len, mic_key, K1, K2); + aes_cmac(key_len, mic_key, K1, K2, data_length, data, mic); +} +#endif + +#ifdef BCMAES_GENTABLE +/* AES table expansion for rijndael-alg-fst.c + * - can compute all 10 tables needed by rijndael-alg-fst.c + * - only stores table entries for non-NULL entries in "at" structure, so + * can be used to generate a subset of the tables if only some are needed + */ +void +aes_gen_tables(const uint8 *S, const uint8 *Si, aes_tables_t at) +{ + int k; + uint8 s2, s3; + uint8 si2, si4, si8, si9, sib, sid, sie; + uint32 Te0tmp, Td0tmp; + + for (k = 0; k < AES_SBOX_ENTRIES; k++) { + /* 2 X S[k] */ + XTIME(S[k], s2); + + /* 3 X S[k] */ + s3 = s2 ^ S[k]; + + /* 2 X Si[k] */ + XTIME(Si[k], si2); + + /* 4 X Si[k] */ + XTIME(si2, si4); + + /* 8 X Si[k] */ + XTIME(si4, si8); + + /* 9 X S[k] */ + si9 = si8 ^ Si[k]; + + /* 11 X S[k] */ + sib = si9 ^ si2; + + /* 13 X S[k] */ + sid = si8 ^ si4 ^ Si[k]; + + /* 14 X S[k] */ + sie = si8 ^ si4 ^ si2; + + Te0tmp = (s2 << 24) | (S[k] << 16) | (S[k] << 8) | s3; + if (at.Te0 != NULL) + at.Te0[k] = Te0tmp; + if (at.Te1 != NULL) + at.Te1[k] = ROTATE(Te0tmp, 24); + if (at.Te2 != NULL) + at.Te2[k] = ROTATE(Te0tmp, 16); + if (at.Te3 != NULL) + at.Te3[k] = ROTATE(Te0tmp, 8); + if (at.Te4 != NULL) + at.Te4[k] = (S[k] << 24) | (S[k] << 16) | (S[k] << 8) | S[k]; + + Td0tmp = (sie << 24) | (si9 << 16) | (sid << 8) | sib; + if (at.Td0 != NULL) + at.Td0[k] = Td0tmp; + if (at.Td1 != NULL) + at.Td1[k] = ROTATE(Td0tmp, 24); + if (at.Td2 != NULL) + at.Td2[k] = ROTATE(Td0tmp, 16); + if (at.Td3 != NULL) + at.Td3[k] = ROTATE(Td0tmp, 8); + if (at.Td4 != NULL) + at.Td4[k] = (Si[k] << 24) | (Si[k] << 16) | (Si[k] << 8) | Si[k]; + } +} +#endif /* BCMAES_GENTABLE */ + +#ifdef BCMAES_TEST +#include "aes_vectors.h" + +static uint8 +get_nonce_1st_byte(struct dot11_header *h) +{ + uint16 fc, subtype; + uint16 qc; + bool wds, qos; + + qc = 0; + fc = ltoh16(h->fc); + subtype = (fc & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT; + wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS)); + /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */ + qos = (FC_TYPE(fc) == FC_TYPE_DATA) && (subtype & FC_SUBTYPE_QOS_DATA); + + if (qos) { + qc = ltoh16(*((uint16 *)((uchar *)h + + (wds ? DOT11_A4_HDR_LEN : DOT11_A3_HDR_LEN)))); + } + + /* nonce = priority octet || A2 || PN, !legacy */ + return (uint8)(QOS_TID(qc) & 0x0f); +} + +int main(int argc, char **argv) +{ + uint8 output[BUFSIZ], input2[BUFSIZ]; + int retv, k, fail = 0; + uint32 rk[4 * (AES_MAXROUNDS + 1)]; + +#ifdef BCMAES_GENTABLE + uint32 Te0test[256], Te1test[256], Te2test[256], Te3test[256], Te4test[256]; + uint32 Td0test[256], Td1test[256], Td2test[256], Td3test[256], Td4test[256]; + + aes_tables_t at = { + Te0test, Te1test, Te2test, Te3test, Te4test, + Td0test, Td1test, Td2test, Td3test, Td4test + }; +#endif /* BCMAES_GENTABLE */ + + /* AES-CBC */ + dbg(("%s: AES-CBC\n", *argv)); + for (k = 0; k < NUM_CBC_VECTORS; k++) { + rijndaelKeySetupEnc(rk, aes_cbc_vec[k].key, + AES_KEY_BITLEN(aes_cbc_vec[k].kl)); + retv = aes_cbc_encrypt(rk, aes_cbc_vec[k].kl, + aes_cbc_vec[k].nonce, aes_cbc_vec[k].il, + aes_cbc_vec[k].input, output); + pres("AES CBC Encrypt: ", aes_cbc_vec[k].il, output); + + if (retv == -1) { + dbg(("%s: aes_cbc_encrypt failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_cbc_vec[k].ref, aes_cbc_vec[k].il) != 0) { + dbg(("%s: aes_cbc_encrypt failed\n", *argv)); + fail++; + } + + rijndaelKeySetupDec(rk, aes_cbc_vec[k].key, + AES_KEY_BITLEN(aes_cbc_vec[k].kl)); + retv = aes_cbc_decrypt(rk, aes_cbc_vec[k].kl, + aes_cbc_vec[k].nonce, aes_cbc_vec[k].il, + aes_cbc_vec[k].ref, input2); + pres("AES CBC Decrypt: ", aes_cbc_vec[k].il, input2); + + if (retv == -1) { + dbg(("%s: aes_cbc_decrypt failed\n", *argv)); + fail++; + } + if (bcmp(aes_cbc_vec[k].input, input2, aes_cbc_vec[k].il) != 0) { + dbg(("%s: aes_cbc_decrypt failed\n", *argv)); + fail++; + } + } + + /* AES-CTR, full blocks */ + dbg(("%s: AES-CTR, full blocks\n", *argv)); + for (k = 0; k < NUM_CTR_VECTORS; k++) { + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, aes_ctr_vec[k].il, + aes_ctr_vec[k].input, output); + pres("AES CTR Encrypt: ", aes_ctr_vec[k].il, output); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_ctr_vec[k].ref, aes_ctr_vec[k].il) != 0) { + dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, aes_ctr_vec[k].il, + aes_ctr_vec[k].ref, input2); + pres("AES CTR Decrypt: ", aes_ctr_vec[k].il, input2); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(aes_ctr_vec[k].input, input2, aes_ctr_vec[k].il) != 0) { + dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv)); + fail++; + } + } + + /* AES-CTR, one partial block */ + dbg(("%s: AES-CTR, one partial block\n", *argv)); + for (k = 0; k < NUM_CTR_VECTORS; k++) { + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, k+1, + aes_ctr_vec[k].input, output); + pres("AES CTR Partial Block Encrypt: ", k+1, output); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_ctr_vec[k].ref, k + 1) != 0) { + dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, k + 1, + aes_ctr_vec[k].ref, input2); + pres("AES CTR Partial Block Decrypt: ", k + 1, input2); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(aes_ctr_vec[k].input, input2, k + 1) != 0) { + dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv)); + fail++; + } + } + + /* AES-CTR, multi-block partial */ + dbg(("%s: AES-CTR, multi-block partial\n", *argv)); + for (k = 0; k < NUM_CTR_VECTORS; k++) { + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, AES_BLOCK_SZ + NUM_CTR_VECTORS+k+1, + aes_ctr_vec[k].input, output); + pres("AES CTR Partial Multi-Block Encrypt: ", + AES_BLOCK_SZ + NUM_CTR_VECTORS + k + 1, output); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_ctr_vec[k].ref, AES_BLOCK_SZ+NUM_CTR_VECTORS + k + 1) != 0) { + dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ctr_vec[k].key, + AES_KEY_BITLEN(aes_ctr_vec[k].kl)); + retv = aes_ctr_crypt(rk, aes_ctr_vec[k].kl, + aes_ctr_vec[k].nonce, AES_BLOCK_SZ + NUM_CTR_VECTORS + k + 1, + aes_ctr_vec[k].ref, input2); + pres("AES CTR Partial Multi-Block Decrypt: ", + AES_BLOCK_SZ + NUM_CTR_VECTORS + k + 1, input2); + + if (retv) { + dbg(("%s: aes_ctr_crypt failed\n", *argv)); + fail++; + } + if (bcmp(aes_ctr_vec[k].input, input2, + AES_BLOCK_SZ + NUM_CTR_VECTORS + k + 1) != 0) { + dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv)); + fail++; + } + } + + /* AES-CCM */ + dbg(("%s: AES-CCM\n", *argv)); + for (k = 0; k < NUM_CCM_VECTORS; k++) { + rijndaelKeySetupEnc(rk, aes_ccm_vec[k].key, + AES_KEY_BITLEN(aes_ccm_vec[k].kl)); + retv = aes_ccm_mac(rk, aes_ccm_vec[k].kl, + aes_ccm_vec[k].nonce, aes_ccm_vec[k].al, + aes_ccm_vec[k].aad, aes_ccm_vec[k].il, + aes_ccm_vec[k].input, output); + + if (retv) { + dbg(("%s: aes_ccm_mac failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_ccm_vec[k].mac, AES_CCM_AUTH_LEN) != 0) { + dbg(("%s: aes_ccm_mac failed\n", *argv)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ccm_vec[k].key, + AES_KEY_BITLEN(aes_ccm_vec[k].kl)); + retv = aes_ccm_encrypt(rk, aes_ccm_vec[k].kl, + aes_ccm_vec[k].nonce, aes_ccm_vec[k].al, + aes_ccm_vec[k].aad, aes_ccm_vec[k].il, + aes_ccm_vec[k].input, output, &output[aes_ccm_vec[k].il]); + pres("AES CCM Encrypt: ", aes_ccm_vec[k].il + AES_CCM_AUTH_LEN, output); + + if (retv) { + dbg(("%s: aes_ccm_encrypt failed\n", *argv)); + fail++; + } + if (bcmp(output, aes_ccm_vec[k].ref, aes_ccm_vec[k].il + AES_CCM_AUTH_LEN) != 0) { + dbg(("%s: aes_ccm_encrypt failed\n", *argv)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ccm_vec[k].key, + AES_KEY_BITLEN(aes_ccm_vec[k].kl)); + retv = aes_ccm_decrypt(rk, aes_ccm_vec[k].kl, + aes_ccm_vec[k].nonce, aes_ccm_vec[k].al, + aes_ccm_vec[k].aad, aes_ccm_vec[k].il + AES_CCM_AUTH_LEN, + aes_ccm_vec[k].ref, input2); + pres("AES CCM Decrypt: ", aes_ccm_vec[k].il + AES_CCM_AUTH_LEN, input2); + + if (retv) { + dbg(("%s: aes_ccm_decrypt failed\n", *argv)); + fail++; + } + if (bcmp(aes_ccm_vec[k].input, input2, aes_ccm_vec[k].il) != 0) { + dbg(("%s: aes_ccm_decrypt failed\n", *argv)); + fail++; + } + } + + /* AES-CCMP */ + dbg(("%s: AES-CCMP\n", *argv)); + for (k = 0; k < NUM_CCMP_VECTORS; k++) { + uint8 nonce_1st_byte; + dbg(("%s: AES-CCMP vector %d\n", *argv, k)); + rijndaelKeySetupEnc(rk, aes_ccmp_vec[k].key, + AES_KEY_BITLEN(aes_ccmp_vec[k].kl)); + bcopy(aes_ccmp_vec[k].input, output, aes_ccmp_vec[k].il); + nonce_1st_byte = get_nonce_1st_byte((struct dot11_header *)output); + retv = aes_ccmp_encrypt(rk, aes_ccmp_vec[k].kl, + aes_ccmp_vec[k].il, output, + aes_ccmp_vec[k].flags[2], + nonce_1st_byte); + + if (retv) { + dbg(("%s: aes_ccmp_encrypt of vector %d returned error\n", *argv, k)); + fail++; + } + if (bcmp(output, aes_ccmp_vec[k].ref, + aes_ccmp_vec[k].il+AES_CCM_AUTH_LEN) != 0) { + dbg(("%s: aes_ccmp_encrypt of vector %d reference mismatch\n", *argv, k)); + fail++; + } + + rijndaelKeySetupEnc(rk, aes_ccmp_vec[k].key, + AES_KEY_BITLEN(aes_ccmp_vec[k].kl)); + bcopy(aes_ccmp_vec[k].ref, output, aes_ccmp_vec[k].il+AES_CCM_AUTH_LEN); + nonce_1st_byte = get_nonce_1st_byte((struct dot11_header *)output); + retv = aes_ccmp_decrypt(rk, aes_ccmp_vec[k].kl, + aes_ccmp_vec[k].il+AES_CCM_AUTH_LEN, output, + aes_ccmp_vec[k].flags[2], + nonce_1st_byte); + + if (retv) { + dbg(("%s: aes_ccmp_decrypt of vector %d returned error %d\n", + *argv, k, retv)); + fail++; + } + if (bcmp(output, aes_ccmp_vec[k].input, aes_ccmp_vec[k].il) != 0) { + dbg(("%s: aes_ccmp_decrypt of vector %d reference mismatch\n", *argv, k)); + fail++; + } + } + + +#ifdef BCMAES_GENTABLE + aes_gen_tables(AES_Sbox, AES_Inverse_Sbox, at); + ptable("Te0", Te0test); + ptable("Te1", Te1test); + ptable("Te2", Te2test); + ptable("Te3", Te3test); + ptable("Te4", Te4test); + + ptable("Td0", Td0test); + ptable("Td1", Td1test); + ptable("Td2", Td2test); + ptable("Td3", Td3test); + ptable("Td4", Td4test); +#endif /* BCMAES_GENTABLE */ + + fprintf(stderr, "%s: %s\n", *argv, fail ? "FAILED" : "PASSED"); + return (fail); +} + +#endif /* BCMAES_TEST */ diff --git a/release/src-rt/bcmcrypto/aes_vectors.h b/release/src-rt/bcmcrypto/aes_vectors.h new file mode 100755 index 0000000000..eafac152e1 --- /dev/null +++ b/release/src-rt/bcmcrypto/aes_vectors.h @@ -0,0 +1,1066 @@ +/* + * aes_vectors.h + * AES test vectors + * + * Copyright 2003, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; the + * contents of this file may not be disclosed to third parties, copied or + * duplicated in any form, in whole or in part, without the prior written + * permission of Broadcom Corporation. + * + * $Id: aes_vectors.h,v 1.6.218.1 2010-05-28 15:25:49 Exp $ + */ + +#include + +/* Test vector data from NIST Special Publication 800-38A */ + +/* F.2.1 CBC-AES128.Encrypt and F.2.2 CBC-AES128.Decrypt */ +uint8 key_00[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + +uint8 nonce_00[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + +uint8 input_00[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_00[] = { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, + 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, + 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 + }; + + +/* F.2.3 CBC-AES192.Encrypt and F.2.4 CBC-AES192.Decrypt */ +uint8 key_01[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + +uint8 nonce_01[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + +uint8 input_01[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_01[] = { + 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, + 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, + 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a, + 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, + 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0, + 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, + 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd + }; + + +/* F.2.5 CBC-AES256.Encrypt and F.2.6 CBC-AES256.Decrypt */ +uint8 key_02[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + +uint8 nonce_02[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + +uint8 input_02[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_02[] = { + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, + 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b + }; + + +/* F.5.1 CTR-AES128.Encrypt and F.5.2 CTR-AES128.Decrypt */ +uint8 key_03[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + +uint8 nonce_03[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + +uint8 input_03[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_03[] = { + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, + 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, + 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee + }; + + +/* F.5.3 CTR-AES192.Encrypt and F.5.4 CTR-AES192.Decrypt */ +uint8 key_04[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + +uint8 nonce_04[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + +uint8 input_04[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_04[] = { + 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, + 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, + 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94, + 0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, + 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7, + 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, + 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50 + }; + +/* F.5.5 CTR-AES256.Encrypt and F.5.6 CTR-AES256.Decrypt */ +uint8 key_05[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + +uint8 nonce_05[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + +uint8 input_05[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + +uint8 ref_05[] = { + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, + 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, + 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, + 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, + 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6 + }; + + +typedef struct { + int kl; + uint8 *key; + uint8 *nonce; + int il; + uint8 *input; + uint8 *ref; +} aes_vector_t; + +#define AES_VECTOR_ENTRY(x) \ + { sizeof(key_##x), key_##x, nonce_##x, sizeof(input_##x), input_##x, ref_##x } + +aes_vector_t aes_cbc_vec[] = { + AES_VECTOR_ENTRY(00), + AES_VECTOR_ENTRY(01), + AES_VECTOR_ENTRY(02), + }; +#define NUM_CBC_VECTORS (sizeof(aes_cbc_vec)/sizeof(aes_cbc_vec[0])) + +aes_vector_t aes_ctr_vec[] = { + AES_VECTOR_ENTRY(03), + AES_VECTOR_ENTRY(04), + AES_VECTOR_ENTRY(05) + }; +#define NUM_CTR_VECTORS (sizeof(aes_ctr_vec)/sizeof(aes_ctr_vec[0])) + + +/* Test vector data from: RFC3610 Counter with CBC-MAC (CCM) */ + +/* Packet Vector #1 */ +uint8 key_06[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_06[] = { + 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_06[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 input_06[] = { + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E + }; + +uint8 mac_06[] = { + 0x2D, 0xC6, 0x97, 0xE4, 0x11, 0xCA, 0x83, 0xA8 + }; + +uint8 ref_06[] = { + 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, + 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, + 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84, 0x17, + 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0 + }; + +/* Packet Vector #2 */ +uint8 key_07[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_07[] = { + 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_07[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 input_07[] = { + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 mac_07[] = { + 0xF7, 0xB9, 0x05, 0x6A, 0x86, 0x92, 0x6C, 0xF3 + }; + +uint8 ref_07[] = { + 0x72, 0xC9, 0x1A, 0x36, 0xE1, 0x35, 0xF8, 0xCF, + 0x29, 0x1C, 0xA8, 0x94, 0x08, 0x5C, 0x87, 0xE3, + 0xCC, 0x15, 0xC4, 0x39, 0xC9, 0xE4, 0x3A, 0x3B, + 0xA0, 0x91, 0xD5, 0x6E, 0x10, 0x40, 0x09, 0x16 + }; + +/* Packet Vector #3 */ +uint8 key_08[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_08[] = { + 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x02, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_08[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 input_08[] = { + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20 + }; + +uint8 mac_08[] = { + 0x73, 0xB4, 0x67, 0x75, 0xC0, 0x26, 0xDE, 0xAA + }; + +uint8 ref_08[] = { + 0x51, 0xB1, 0xE5, 0xF4, 0x4A, 0x19, 0x7D, 0x1D, + 0xA4, 0x6B, 0x0F, 0x8E, 0x2D, 0x28, 0x2A, 0xE8, + 0x71, 0xE8, 0x38, 0xBB, 0x64, 0xDA, 0x85, 0x96, + 0x57, 0x4A, 0xDA, 0xA7, 0x6F, 0xBD, 0x9F, 0xB0, + 0xC5 + }; + +/* Packet Vector #4 */ +uint8 key_09[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_09[] = { + 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_09[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B + }; + +uint8 input_09[] = { + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E + }; + +uint8 mac_09[] = { + 0x4B, 0x4F, 0x4B, 0x39, 0xB5, 0x93, 0xE6, 0xBF + }; + +uint8 ref_09[] = { + 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, + 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, + 0xCD, 0xAC, 0x8C, 0x96, 0xC8, 0x61, 0xB9, 0xC9, + 0xE6, 0x1E, 0xF1 + }; + +/* Packet Vector #5 */ +uint8 key_10[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_10[] = { + 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_10[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B + }; + +uint8 input_10[] = { + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 mac_10[] = { + 0x48, 0xB9, 0xE8, 0x82, 0x55, 0x05, 0x4A, 0xB5 + }; + +uint8 ref_10[] = { + 0xDC, 0xF1, 0xFB, 0x7B, 0x5D, 0x9E, 0x23, 0xFB, + 0x9D, 0x4E, 0x13, 0x12, 0x53, 0x65, 0x8A, 0xD8, + 0x6E, 0xBD, 0xCA, 0x3E, 0x51, 0xE8, 0x3F, 0x07, + 0x7D, 0x9C, 0x2D, 0x93 + }; + +/* Packet Vector #6 */ +uint8 key_11[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF + }; + +uint8 nonce_11[] = { + 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x05, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 + }; + +uint8 aad_11[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B + }; + +uint8 input_11[] = { + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20 + }; + +uint8 mac_11[] = { + 0xA5, 0x27, 0xD8, 0x15, 0x6A, 0xC3, 0x59, 0xBF + }; + +uint8 ref_11[] = { + 0x6F, 0xC1, 0xB0, 0x11, 0xF0, 0x06, 0x56, 0x8B, + 0x51, 0x71, 0xA4, 0x2D, 0x95, 0x3D, 0x46, 0x9B, + 0x25, 0x70, 0xA4, 0xBD, 0x87, 0x40, 0x5A, 0x04, + 0x43, 0xAC, 0x91, 0xCB, 0x94 + }; + + +typedef struct { + int kl; + uint8 *key; + uint8 *nonce; + int al; + uint8 *aad; + int il; + uint8 *input; + uint8 *mac; + uint8 *ref; +} aes_ccm_vector_t; + +#define AES_CCM_VECTOR_ENTRY(x) \ +{ \ + sizeof(key_##x), key_##x, nonce_##x, sizeof(aad_##x), aad_##x, \ + sizeof(input_##x), input_##x, mac_##x, ref_##x \ +} + +aes_ccm_vector_t aes_ccm_vec[] = { + AES_CCM_VECTOR_ENTRY(06), + AES_CCM_VECTOR_ENTRY(07), + AES_CCM_VECTOR_ENTRY(08), + AES_CCM_VECTOR_ENTRY(09), + AES_CCM_VECTOR_ENTRY(10), + AES_CCM_VECTOR_ENTRY(11), + AES_CCM_VECTOR_ENTRY(99) + }; +#define NUM_CCM_VECTORS (sizeof(aes_ccm_vec)/sizeof(aes_ccm_vec[0])) + + +/* Test vectors from 802.11i Draft 7.0 */ +/* CCMP test mpdu 1 - works for both legacy and new ucode, so try it both ways */ +uint8 key_20[] = { + 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, + 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f + }; + +uint8 input_20[] = { + 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, + 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, + 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, + 0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5, + 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, + 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, + 0x7e, 0x78, 0xa0, 0x50 + }; + +uint8 ref_20[] = { + 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, + 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, + 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, + 0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5, + 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, + 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, + 0x3c, 0x04, 0xd0, 0x19, 0x78, 0x45, 0xce, 0x0b, + 0x16, 0xf9, 0x76, 0x23 + }; + +/* WDS, WME, legacy */ +bool flags_20[] = { FALSE, FALSE, TRUE }; + +uint8 key_21[] = { + 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, + 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f + }; + +uint8 input_21[] = { + 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, + 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, + 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, + 0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5, + 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, + 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, + 0x7e, 0x78, 0xa0, 0x50 + }; + +uint8 ref_21[] = { + 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, + 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, + 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, + 0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5, + 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, + 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, + 0x3c, 0x04, 0xd0, 0x19, 0x78, 0x45, 0xce, 0x0b, + 0x16, 0xf9, 0x76, 0x23 + }; + +/* WDS, WME, legacy */ +bool flags_21[] = { FALSE, FALSE, FALSE }; + +/* CCMP test mpdu 2 */ +uint8 key_22[] = { + 0x8f, 0x7a, 0x05, 0x3f, 0xa5, 0x77, 0xa5, 0x59, + 0x75, 0x29, 0x27, 0x20, 0x97, 0xa6, 0x03, 0xd5 + }; + +uint8 input_22[] = { + 0x38, 0xc0, 0x6a, 0x51, 0xea, 0x10, 0x0c, 0x84, + 0x68, 0x50, 0xee, 0xc1, 0x76, 0x2c, 0x88, 0xde, + 0xaf, 0x2e, 0xe9, 0xf4, 0x6a, 0x07, 0xe0, 0xcc, + 0xea, 0x97, 0x00, 0xa0, 0xba, 0xcb, 0xf3, 0x31, + 0x83, 0xa0, 0x63, 0x4b, 0x5e, 0xd7, 0x62, 0x7e, + 0xb9, 0xdf, 0x22, 0x5e, 0x05, 0x74, 0x03, 0x42, + 0xde, 0x19, 0x41, 0x17 + }; + +uint8 ref_22[] = { + 0x38, 0xc0, 0x6a, 0x51, 0xea, 0x10, 0x0c, 0x84, + 0x68, 0x50, 0xee, 0xc1, 0x76, 0x2c, 0x88, 0xde, + 0xaf, 0x2e, 0xe9, 0xf4, 0x6a, 0x07, 0xe0, 0xcc, + 0xea, 0x97, 0x00, 0xa0, 0xba, 0xcb, 0xf3, 0x31, + 0x81, 0x4b, 0x69, 0x65, 0xd0, 0x5b, 0xf2, 0xb2, + 0xed, 0x38, 0xd4, 0xbe, 0xb0, 0x69, 0xfe, 0x82, + 0x71, 0x4a, 0x61, 0x0b, 0x54, 0x2f, 0xbf, 0x8d, + 0xa0, 0x6a, 0xa4, 0xae + }; + +bool flags_22[] = { FALSE, FALSE, FALSE }; + +/* CCMP test mpdu 3 */ +uint8 key_23[] = { + 0x40, 0xcf, 0xb7, 0xa6, 0x2e, 0x88, 0x01, 0x3b, + 0xd6, 0xd3, 0xaf, 0xfc, 0xc1, 0x91, 0x04, 0x1e + }; + +uint8 input_23[] = { + 0xb8, 0xc8, 0xdc, 0x61, 0xd9, 0x57, 0x7d, 0xf7, + 0x63, 0xc8, 0xb6, 0xa8, 0x8a, 0xdf, 0x36, 0x91, + 0xdc, 0x4a, 0x8b, 0xca, 0x94, 0xdd, 0x60, 0x82, + 0x20, 0x85, 0xae, 0xa5, 0x00, 0xa0, 0xf3, 0xa0, + 0xdc, 0x2f, 0x2c, 0x1b, 0xd0, 0x36, 0x83, 0x1c, + 0x95, 0x49, 0x6c, 0x5f, 0x4d, 0xbf, 0x3d, 0x55, + 0x9e, 0x72, 0xde, 0x80, 0x2a, 0x18 + }; + +uint8 ref_23[] = { + 0xb8, 0xc8, 0xdc, 0x61, 0xd9, 0x57, 0x7d, 0xf7, + 0x63, 0xc8, 0xb6, 0xa8, 0x8a, 0xdf, 0x36, 0x91, + 0xdc, 0x4a, 0x8b, 0xca, 0x94, 0xdd, 0x60, 0x82, + 0x20, 0x85, 0xae, 0xa5, 0x00, 0xa0, 0xf3, 0xa0, + 0xdc, 0x2f, 0x89, 0xd8, 0x58, 0x03, 0x40, 0xb6, + 0x26, 0xa0, 0xb6, 0xd4, 0xd0, 0x13, 0xbf, 0x18, + 0xf2, 0x91, 0xb8, 0x96, 0x46, 0xc8, 0xfd, 0x1f, + 0x1f, 0x61, 0xa9, 0xfb, 0x4b, 0xb3 + }; + +bool flags_23[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 4 */ +uint8 key_24[] = { + 0x8c, 0x89, 0xa2, 0xeb, 0xc9, 0x6c, 0x76, 0x02, + 0x70, 0x7f, 0xcf, 0x24, 0xb3, 0x2d, 0x38, 0x33 + }; + +uint8 input_24[] = { + 0xa8, 0xca, 0x3a, 0x11, 0x71, 0x2a, 0x9d, 0xdf, + 0x11, 0xdb, 0x8e, 0xf8, 0x22, 0x73, 0x47, 0x01, + 0x59, 0x14, 0x0d, 0xd6, 0x46, 0xa2, 0xc0, 0x2f, + 0x67, 0xa5, 0xe3, 0x0f, 0x00, 0x20, 0x5a, 0xa5, + 0x70, 0xf6, 0x4f, 0xad, 0x2b, 0x1c, 0x29, 0x0f, + 0xa5, 0xeb, 0xd8, 0x72, 0xfb, 0xc3, 0xf3, 0xa0, + 0x74, 0x89, 0x8f, 0x8b, 0x2f, 0xbb + }; + +uint8 ref_24[] = { + 0xa8, 0xca, 0x3a, 0x11, 0x71, 0x2a, 0x9d, 0xdf, + 0x11, 0xdb, 0x8e, 0xf8, 0x22, 0x73, 0x47, 0x01, + 0x59, 0x14, 0x0d, 0xd6, 0x46, 0xa2, 0xc0, 0x2f, + 0x67, 0xa5, 0xe3, 0x0f, 0x00, 0x20, 0x5a, 0xa5, + 0x70, 0xf6, 0x9d, 0x59, 0xb1, 0x5f, 0x37, 0x14, + 0x48, 0xc2, 0x30, 0xf4, 0xd7, 0x39, 0x05, 0x2e, + 0x13, 0xab, 0x3b, 0x1a, 0x7b, 0x10, 0x31, 0xfc, + 0x88, 0x00, 0x4f, 0x35, 0xee, 0x3d + }; + +bool flags_24[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 5 */ +uint8 key_25[] = { + 0xa5, 0x74, 0xd5, 0x14, 0x3b, 0xb2, 0x5e, 0xfd, + 0xde, 0xff, 0x30, 0x12, 0x2f, 0xdf, 0xd0, 0x66 + }; + +uint8 input_25[] = { + 0x88, 0xda, 0x18, 0x41, 0x45, 0xde, 0xc6, 0x9a, + 0x74, 0x80, 0xf3, 0x51, 0x94, 0x6b, 0xc9, 0x6b, + 0xe2, 0x76, 0xfb, 0xe6, 0xc1, 0x27, 0x80, 0xf2, + 0x4b, 0x19, 0x37, 0x0e, 0x00, 0xa0, 0x3c, 0xe0, + 0xff, 0xa7, 0x28, 0x96, 0x9b, 0x95, 0x4f, 0x26, + 0x3a, 0x80, 0x18, 0xa9, 0xef, 0x70, 0xa8, 0xb0, + 0x51, 0x46, 0x24, 0x81, 0x92, 0x2e + }; + +uint8 ref_25[] = { + 0x88, 0xda, 0x18, 0x41, 0x45, 0xde, 0xc6, 0x9a, + 0x74, 0x80, 0xf3, 0x51, 0x94, 0x6b, 0xc9, 0x6b, + 0xe2, 0x76, 0xfb, 0xe6, 0xc1, 0x27, 0x80, 0xf2, + 0x4b, 0x19, 0x37, 0x0e, 0x00, 0xa0, 0x3c, 0xe0, + 0xff, 0xa7, 0xeb, 0x4a, 0xe4, 0x95, 0x6a, 0x80, + 0x1d, 0xa9, 0x62, 0x4b, 0x7e, 0x0c, 0x18, 0xb2, + 0x3e, 0x61, 0x5e, 0xc0, 0x3a, 0xf6, 0xce, 0x0c, + 0x3b, 0xe1, 0x97, 0xd3, 0x05, 0xeb + }; + +bool flags_25[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 6 */ +uint8 key_26[] = { + 0xf7, 0x1e, 0xea, 0x4e, 0x1f, 0x58, 0x80, 0x4b, + 0x97, 0x17, 0x23, 0x0a, 0xd0, 0x61, 0x46, 0x41 + }; + +uint8 input_26[] = { + 0x88, 0x52, 0xe1, 0x1f, 0x5a, 0xf2, 0x84, 0x30, + 0xfd, 0xab, 0xbf, 0xf9, 0x43, 0xb9, 0xf9, 0xa6, + 0xab, 0x1d, 0x98, 0xc7, 0xfe, 0x73, 0x50, 0x71, + 0x3d, 0x6a, 0x89, 0x89, 0x00, 0x60, 0xa4, 0xec, + 0x81, 0x6b, 0xab, 0xfd, 0xa2, 0x2d, 0x3a, 0x0b, + 0xfc, 0x9c, 0xc1, 0xfc, 0x07, 0x93, 0x63, 0xc2, + 0xfc, 0xa1, 0x43, 0xe6, 0xeb, 0x1d + }; + +uint8 ref_26[] = { + 0x88, 0x52, 0xe1, 0x1f, 0x5a, 0xf2, 0x84, 0x30, + 0xfd, 0xab, 0xbf, 0xf9, 0x43, 0xb9, 0xf9, 0xa6, + 0xab, 0x1d, 0x98, 0xc7, 0xfe, 0x73, 0x50, 0x71, + 0x3d, 0x6a, 0x89, 0x89, 0x00, 0x60, 0xa4, 0xec, + 0x81, 0x6b, 0x9a, 0x70, 0x9b, 0x60, 0xa3, 0x9d, + 0x40, 0xb1, 0xdf, 0xb6, 0x12, 0xe1, 0x8b, 0x5f, + 0x11, 0x4b, 0xad, 0xb6, 0xcc, 0x86, 0x30, 0x9a, + 0x8d, 0x5c, 0x46, 0x6b, 0xbb, 0x71 + }; + +bool flags_26[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 7 */ +uint8 key_27[] = { + 0x1b, 0xdb, 0x34, 0x98, 0x0e, 0x03, 0x81, 0x24, + 0xa1, 0xdb, 0x1a, 0x89, 0x2b, 0xec, 0x36, 0x6a + }; + +uint8 input_27[] = { + 0x18, 0x79, 0x81, 0x46, 0x9b, 0x50, 0xf4, 0xfd, + 0x56, 0xf6, 0xef, 0xec, 0x95, 0x20, 0x16, 0x91, + 0x83, 0x57, 0x0c, 0x4c, 0xcd, 0xee, 0x20, 0xa0, + 0x23, 0xe7, 0x00, 0xe0, 0x73, 0x40, 0xec, 0x5e, + 0x98, 0xbe, 0xca, 0x86, 0xf4, 0xb3, 0x8d, 0xa2, + 0x0c, 0xfd, 0xf2, 0x47, 0x24, 0xc5, 0x8e, 0xb8, + 0x35, 0x66, 0x53, 0x39 + }; + +uint8 ref_27[] = { + 0x18, 0x79, 0x81, 0x46, 0x9b, 0x50, 0xf4, 0xfd, + 0x56, 0xf6, 0xef, 0xec, 0x95, 0x20, 0x16, 0x91, + 0x83, 0x57, 0x0c, 0x4c, 0xcd, 0xee, 0x20, 0xa0, + 0x23, 0xe7, 0x00, 0xe0, 0x73, 0x40, 0xec, 0x5e, + 0x12, 0xc5, 0x37, 0xeb, 0xf3, 0xab, 0x58, 0x4e, + 0xf1, 0xfe, 0xf9, 0xa1, 0xf3, 0x54, 0x7a, 0x8c, + 0x13, 0xb3, 0x22, 0x5a, 0x2d, 0x09, 0x57, 0xec, + 0xfa, 0xbe, 0x95, 0xb9 + }; + +bool flags_27[] = { FALSE, FALSE, FALSE }; + +/* CCMP test mpdu 8 */ +uint8 key_28[] = { + 0x6e, 0xac, 0x1b, 0xf5, 0x4b, 0xd5, 0x4e, 0xdb, + 0x23, 0x21, 0x75, 0x43, 0x03, 0x02, 0x4c, 0x71 + }; + +uint8 input_28[] = { + 0xb8, 0xd9, 0x4c, 0x72, 0x55, 0x2d, 0x5f, 0x72, + 0xbb, 0x70, 0xca, 0x3f, 0x3a, 0xae, 0x60, 0xc4, + 0x8b, 0xa9, 0xb5, 0xf8, 0x2c, 0x2f, 0x50, 0xeb, + 0x2a, 0x55, 0xdd, 0xcc, 0x00, 0xa0, 0x6e, 0x99, + 0xfd, 0xce, 0x57, 0xcb, 0x5c, 0x0e, 0x5f, 0xcd, + 0x88, 0x5e, 0x9a, 0x42, 0x39, 0xe9, 0xb9, 0xca, + 0xd6, 0x0d, 0x64, 0x37, 0x59, 0x79 + }; + +uint8 ref_28[] = { + 0xb8, 0xd9, 0x4c, 0x72, 0x55, 0x2d, 0x5f, 0x72, + 0xbb, 0x70, 0xca, 0x3f, 0x3a, 0xae, 0x60, 0xc4, + 0x8b, 0xa9, 0xb5, 0xf8, 0x2c, 0x2f, 0x50, 0xeb, + 0x2a, 0x55, 0xdd, 0xcc, 0x00, 0xa0, 0x6e, 0x99, + 0xfd, 0xce, 0x4b, 0xf2, 0x81, 0xef, 0x8e, 0xc7, + 0x73, 0x9f, 0x91, 0x59, 0x1b, 0x97, 0xa8, 0x7d, + 0xc1, 0x4b, 0x3f, 0xa1, 0x74, 0x62, 0x6d, 0xba, + 0x8e, 0xf7, 0xf0, 0x80, 0x87, 0xdd + }; + +bool flags_28[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 9 */ +uint8 key_29[] = { + 0x49, 0x4b, 0x50, 0x1e, 0x19, 0x46, 0x75, 0x97, + 0x1a, 0x48, 0xd0, 0x8c, 0x5b, 0xc3, 0x53, 0xcb + }; + +uint8 input_29[] = { + 0xa8, 0xf9, 0xc8, 0x42, 0x9a, 0xfb, 0x79, 0x8b, + 0x8a, 0x4b, 0xa4, 0xad, 0x6d, 0x31, 0x99, 0x85, + 0xbc, 0x42, 0x9e, 0x8f, 0x0a, 0xfa, 0xf0, 0x7d, + 0x4a, 0x80, 0xb3, 0x37, 0x00, 0xe0, 0x34, 0xe9, + 0x82, 0xba, 0x25, 0xa9, 0x8f, 0x9c, 0x1b, 0xd9, + 0xc9, 0x3c, 0xf3, 0x83, 0xab, 0x9d, 0x98, 0x15, + 0x2d, 0x76, 0xcb, 0x4a, 0x32, 0xc6 + }; + +uint8 ref_29[] = { + 0xa8, 0xf9, 0xc8, 0x42, 0x9a, 0xfb, 0x79, 0x8b, + 0x8a, 0x4b, 0xa4, 0xad, 0x6d, 0x31, 0x99, 0x85, + 0xbc, 0x42, 0x9e, 0x8f, 0x0a, 0xfa, 0xf0, 0x7d, + 0x4a, 0x80, 0xb3, 0x37, 0x00, 0xe0, 0x34, 0xe9, + 0x82, 0xba, 0x56, 0x1a, 0x0d, 0x06, 0x8e, 0xac, + 0x2e, 0xad, 0xb0, 0xc5, 0x7f, 0xe2, 0xd0, 0xa6, + 0xcc, 0x73, 0x98, 0xb6, 0xdd, 0xbf, 0xcf, 0xe4, + 0x38, 0xcb, 0xea, 0x61, 0xfa, 0x9a + }; + +bool flags_29[] = { FALSE, TRUE, FALSE }; + +/* CCMP test mpdu 10 */ +uint8 key_30[] = { + 0x48, 0x9e, 0x49, 0xbc, 0x3c, 0xfe, 0x3f, 0xce, + 0x38, 0x95, 0x82, 0x0e, 0x87, 0x2e, 0xe1, 0xa3 + }; + +uint8 input_30[] = { + 0x18, 0x4b, 0xe0, 0x63, 0x40, 0xec, 0x29, 0xfa, + 0x75, 0x9b, 0x53, 0xf8, 0x69, 0xfe, 0x27, 0x9a, + 0xf0, 0xf9, 0xf8, 0xa6, 0x54, 0x16, 0x80, 0xe3, + 0x52, 0xbf, 0xd2, 0x70, 0x3d, 0x24, 0xa9, 0xfe, + 0x00, 0x20, 0x75, 0x3e, 0x1d, 0xcf, 0x7f, 0x91, + 0xf2, 0x47, 0x2d, 0x7a, 0x12, 0x1c, 0x9c, 0xdd, + 0x4b, 0x6c, 0x90, 0x80, 0x67, 0x5a, 0x10, 0x20, + 0xaa, 0x00 + }; + +uint8 ref_30[] = { + 0x18, 0x4b, 0xe0, 0x63, 0x40, 0xec, 0x29, 0xfa, + 0x75, 0x9b, 0x53, 0xf8, 0x69, 0xfe, 0x27, 0x9a, + 0xf0, 0xf9, 0xf8, 0xa6, 0x54, 0x16, 0x80, 0xe3, + 0x52, 0xbf, 0xd2, 0x70, 0x3d, 0x24, 0xa9, 0xfe, + 0x00, 0x20, 0x75, 0x3e, 0x1d, 0xcf, 0x25, 0xdf, + 0x51, 0x73, 0x83, 0x5e, 0x4f, 0xba, 0x23, 0xbc, + 0x05, 0xa2, 0x53, 0x88, 0x5e, 0xbe, 0xd3, 0xac, + 0x48, 0x71, 0xc8, 0x68, 0xa7, 0x25, 0x55, 0x2c, + 0x55, 0x65 + }; + +bool flags_30[] = { TRUE, FALSE, FALSE }; + +/* CCMP test mpdu 11 */ +uint8 key_31[] = { + 0x02, 0xbe, 0x5c, 0x45, 0x45, 0x67, 0x2a, 0x07, + 0xe4, 0xe3, 0x14, 0xd7, 0x0f, 0x1f, 0x9e, 0x85 + }; + +uint8 input_31[] = { + 0xb8, 0xdb, 0x6a, 0x54, 0x29, 0x8c, 0x0b, 0xaa, + 0x91, 0x90, 0x34, 0x7c, 0xeb, 0x9a, 0xab, 0xff, + 0xd8, 0x3d, 0x48, 0x86, 0xe5, 0xc2, 0xe0, 0x53, + 0xe2, 0x9d, 0x52, 0x4a, 0xe1, 0x96, 0x3d, 0x62, + 0xd4, 0x55, 0x00, 0xe0, 0x6e, 0x59, 0xd6, 0xd2, + 0xf9, 0xa8, 0x12, 0xe4, 0xa2, 0x8a, 0xf7, 0xf3, + 0x71, 0x4d, 0x4b, 0xf6, 0x62, 0x2e, 0x59, 0x32, + 0xf2, 0x18, 0x45, 0x09 + }; + +uint8 ref_31[] = { + 0xb8, 0xdb, 0x6a, 0x54, 0x29, 0x8c, 0x0b, 0xaa, + 0x91, 0x90, 0x34, 0x7c, 0xeb, 0x9a, 0xab, 0xff, + 0xd8, 0x3d, 0x48, 0x86, 0xe5, 0xc2, 0xe0, 0x53, + 0xe2, 0x9d, 0x52, 0x4a, 0xe1, 0x96, 0x3d, 0x62, + 0xd4, 0x55, 0x00, 0xe0, 0x6e, 0x59, 0xd6, 0xd2, + 0x63, 0x15, 0x50, 0x0f, 0x92, 0x42, 0x95, 0xcd, + 0x3e, 0xaf, 0xbd, 0xc3, 0xe1, 0x51, 0xb1, 0xdf, + 0x46, 0x46, 0x5b, 0x71, 0x68, 0x1f, 0xde, 0xe8, + 0x51, 0x3c, 0x62, 0xdc + }; + +bool flags_31[] = { TRUE, TRUE, FALSE }; + +/* CCMP test mpdu 12 */ +uint8 key_32[] = { + 0x77, 0x07, 0x7e, 0xd7, 0x94, 0x53, 0xe4, 0xa1, + 0x8d, 0x60, 0x43, 0x8c, 0xc6, 0x48, 0x4d, 0x6e + }; + +uint8 input_32[] = { + 0x18, 0x6b, 0xd0, 0x27, 0xaa, 0x28, 0x8b, 0x84, + 0x35, 0xbc, 0xd8, 0xac, 0x5a, 0x7e, 0xc4, 0x44, + 0xe8, 0xb4, 0x62, 0x50, 0x53, 0x8b, 0x80, 0x62, + 0xe8, 0x14, 0x02, 0xc2, 0xee, 0x11, 0x8e, 0xfd, + 0x00, 0xe0, 0x77, 0x1e, 0xb0, 0x50, 0x43, 0x19, + 0x81, 0xa2, 0x33, 0x6d, 0x02, 0xf8, 0xcb, 0x84, + 0x48, 0xd5, 0x42, 0x89, 0x16, 0xbe, 0x95, 0x29, + 0x35, 0x37 + }; + +uint8 ref_32[] = { + 0x18, 0x6b, 0xd0, 0x27, 0xaa, 0x28, 0x8b, 0x84, + 0x35, 0xbc, 0xd8, 0xac, 0x5a, 0x7e, 0xc4, 0x44, + 0xe8, 0xb4, 0x62, 0x50, 0x53, 0x8b, 0x80, 0x62, + 0xe8, 0x14, 0x02, 0xc2, 0xee, 0x11, 0x8e, 0xfd, + 0x00, 0xe0, 0x77, 0x1e, 0xb0, 0x50, 0xcf, 0x71, + 0xb2, 0xcc, 0xbd, 0x59, 0x0b, 0x20, 0x80, 0x07, + 0x92, 0xf3, 0x59, 0xed, 0x1c, 0xfd, 0x74, 0xd8, + 0x00, 0xb4, 0xfd, 0x0f, 0x41, 0xf4, 0x26, 0xbb, + 0x8f, 0x30 + }; + +bool flags_32[] = { TRUE, FALSE, FALSE }; + + +/* Test vectors generated by legacy ucode */ +uint8 key_40[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 + }; + +uint8 input_40[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x30, 0x9f, + 0x07, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, 0xc0, 0xa8, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xa8, 0x0a, 0x01 + }; + +uint8 ref_40[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x30, 0x9f, + 0x07, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x7d, 0x0c, 0xf3, 0xe7, 0x0b, 0x05, 0xb2, + 0x66, 0x2f, 0xf4, 0xe1, 0xc4, 0x86, 0x1f, 0x94, + 0x02, 0x3f, 0x25, 0x41, 0xcf, 0x65, 0xec, 0xd1, + 0x33, 0x70, 0x8f, 0x62, 0x98, 0xa8, 0x72, 0x5f, + 0x67, 0xe3, 0xaf, 0x78, 0xb1, 0x0d, 0x04, 0x08, + 0x95, 0x2e, 0x11, 0x7a + }; + +bool flags_40[] = { FALSE, FALSE, TRUE }; + +uint8 key_41[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 + }; + +uint8 input_41[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0xb0, 0xa0, + 0x09, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, 0xc0, 0xa8, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xa8, 0x0a, 0x01 + }; + +uint8 ref_41[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0xb0, 0xa0, + 0x09, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0xd4, 0xf2, 0x74, 0x0e, 0x45, 0x6f, 0x6a, + 0xe2, 0x7f, 0xcd, 0x98, 0xa6, 0x54, 0x51, 0xb3, + 0x08, 0x7f, 0xf5, 0x68, 0xbe, 0xcf, 0xd0, 0x98, + 0xbc, 0xbd, 0x70, 0x59, 0xa9, 0xc8, 0xc0, 0x09, + 0xcb, 0x5f, 0x1d, 0x99, 0x71, 0x74, 0x5d, 0x39, + 0xe5, 0x52, 0x92, 0xb9 + }; + +bool flags_41[] = { FALSE, FALSE, TRUE }; + +uint8 key_42[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 + }; + +uint8 input_42[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x70, 0xa1, + 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, 0xc0, 0xa8, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xa8, 0x0a, 0x01 + }; + +uint8 ref_42[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x70, 0xa1, + 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x73, 0xb2, 0x72, 0x41, 0xb8, 0x18, 0x10, 0x27, + 0xbc, 0x2e, 0x94, 0x4f, 0x86, 0x14, 0xfb, 0x7d, + 0x54, 0x85, 0xa1, 0x39, 0x52, 0xf0, 0x73, 0x94, + 0x05, 0x8c, 0xe8, 0xf0, 0xf8, 0xc8, 0x09, 0xfb, + 0x3b, 0x99, 0x3a, 0x1d, 0x49, 0xb1, 0xd1, 0x44, + 0xe4, 0x4d, 0xab, 0xaa + }; + +bool flags_42[] = { FALSE, FALSE, TRUE }; + +uint8 key_43[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 + }; + +uint8 input_43[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x20, 0xa2, + 0x0b, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, 0xc0, 0xa8, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xa8, 0x0a, 0x01 + }; + +uint8 ref_43[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0x20, 0xa2, + 0x0b, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xcf, 0x1c, 0x69, 0xfb, 0x5d, 0x67, 0xcd, 0xc2, + 0x9a, 0x93, 0x13, 0xec, 0x71, 0xc8, 0xb2, 0xbb, + 0x3e, 0x25, 0x0e, 0x4c, 0x1d, 0xcb, 0x44, 0x41, + 0x83, 0x6b, 0xc1, 0xb3, 0x25, 0x1d, 0xb0, 0xb2, + 0x58, 0x90, 0x5e, 0xa3, 0x5d, 0x3c, 0xf9, 0xcd, + 0x98, 0x4c, 0xad, 0xd9 + }; + +bool flags_43[] = { FALSE, FALSE, TRUE }; + +uint8 key_44[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, + }; + +uint8 input_44[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0xd0, 0xa2, + 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, 0xc0, 0xa8, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xa8, 0x0a, 0x01, + }; + +uint8 ref_44[] = { + 0x08, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x10, 0x18, 0x90, 0x01, 0xee, + 0x56, 0xb9, 0x99, 0xdd, 0x40, 0x04, 0xd0, 0xa2, + 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xa5, 0x8a, 0xcf, 0x80, 0xe0, 0xe9, 0x96, 0x1f, + 0x95, 0x9e, 0x71, 0x57, 0x7b, 0x4a, 0x77, 0x1d, + 0x15, 0xae, 0x47, 0xa6, 0x2a, 0xfb, 0x9a, 0x65, + 0x3f, 0x3a, 0x19, 0x76, 0x9f, 0x73, 0xfa, 0xa6, + 0xa7, 0x85, 0x6f, 0xb8, 0x5b, 0x3e, 0x54, 0x25, + 0x34, 0x00, 0xa8, 0x44 + }; + +bool flags_44[] = { FALSE, FALSE, TRUE }; + + +typedef struct { + int kl; + uint8 *key; + int il; + uint8 *input; + uint8 *ref; + bool *flags; +} aes_ccmp_vector_t; + +#define AES_CCMP_VECTOR_ENTRY(x) \ + { sizeof(key_##x), key_##x, sizeof(input_##x), input_##x, ref_##x, flags_##x } + +aes_ccmp_vector_t aes_ccmp_vec[] = { + AES_CCMP_VECTOR_ENTRY(20), + AES_CCMP_VECTOR_ENTRY(21), + AES_CCMP_VECTOR_ENTRY(22), + AES_CCMP_VECTOR_ENTRY(23), + AES_CCMP_VECTOR_ENTRY(24), + AES_CCMP_VECTOR_ENTRY(25), + AES_CCMP_VECTOR_ENTRY(26), + AES_CCMP_VECTOR_ENTRY(27), + AES_CCMP_VECTOR_ENTRY(28), + AES_CCMP_VECTOR_ENTRY(29), + AES_CCMP_VECTOR_ENTRY(30), + AES_CCMP_VECTOR_ENTRY(31), + AES_CCMP_VECTOR_ENTRY(32), + AES_CCMP_VECTOR_ENTRY(40), + AES_CCMP_VECTOR_ENTRY(41), + AES_CCMP_VECTOR_ENTRY(42), + AES_CCMP_VECTOR_ENTRY(43), + AES_CCMP_VECTOR_ENTRY(44) + }; +#define NUM_CCMP_VECTORS (sizeof(aes_ccmp_vec)/sizeof(aes_ccmp_vec[0])) diff --git a/release/src-rt/bcmcrypto/aeskeywrap.c b/release/src-rt/bcmcrypto/aeskeywrap.c new file mode 100755 index 0000000000..4d21ed69dc --- /dev/null +++ b/release/src-rt/bcmcrypto/aeskeywrap.c @@ -0,0 +1,291 @@ +/* + * aeskeywrap.c + * Perform RFC3394 AES-based key wrap and unwrap functions. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: aeskeywrap.c,v 1.31 2009-04-21 01:06:59 Exp $ + */ + +#include + +#ifdef BCMDRIVER +#include +#else +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, int len); +extern int bcmp(const void *b1, const void *b2, int len); +#else +#include +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#endif /* __GNUC__ */ +#include /* for size_t */ +#endif /* BCMDRIVER */ + +#include +#include +#include + +#ifdef BCMAESKEYWRAP_TEST +#include + +#define dbg(args) printf args + +void pinter(const char *label, const uint8 *A, const size_t il, const uint8 *R) +{ + unsigned int k; + printf("%s", label); + for (k = 0; k < AKW_BLOCK_LEN; k++) + printf("%02X", A[k]); + printf(" "); + for (k = 0; k < il; k++) { + printf("%02X", R[k]); + if (!((k+1)%AKW_BLOCK_LEN)) + printf(" "); + } + printf("\n"); +} + +void pres(const char *label, const size_t len, const uint8 *data) +{ + unsigned int k; + printf("%lu %s", (unsigned long)len, label); + for (k = 0; k < len; k++) { + printf("%02x", data[k]); + if (!((k + 1) % AKW_BLOCK_LEN)) + printf(" "); + } + printf("\n"); +} +#else +#define dbg(args) +#define pinter(label, A, il, R) +#endif /* BCMAESKEYWRAP_TEST */ + +static const uint8 aeskeywrapIV[] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 }; + +/* aes_wrap: perform AES-based keywrap function defined in RFC3394 + * return 0 on success, 1 on error + * input is il bytes + * output is (il+8) bytes + */ +int +BCMROMFN(aes_wrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output) +{ + uint32 rk[4*(AES_MAXROUNDS+1)]; + uint8 A[AES_BLOCK_SZ]; + uint8 R[AKW_MAX_WRAP_LEN]; + uint8 B[AES_BLOCK_SZ]; + int n = (int)(il/AKW_BLOCK_LEN), i, j, k; + + /* validate kl (must be valid AES key length) */ + if ((kl != 16) && (kl != 24) && (kl != 32)) { + dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl)); + return (1); + } + if (il > AKW_MAX_WRAP_LEN) { + dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il)); + return (1); + } + if (il % AKW_BLOCK_LEN) { + dbg(("aes_wrap: input length %lu must be a multiple of block length\n", + (unsigned long)il)); + return (1); + } + + dbg((" Input:\n")); + dbg((" KEK: ")); + for (k = 0; k < (int)kl; k++) + dbg(("%02X", key[k])); + dbg(("\n Key Data: ")); + for (k = 0; k < (int)il; k++) + dbg(("%02X", input[k])); + dbg(("\n\n Wrap: \n")); + + rijndaelKeySetupEnc(rk, key, (int)AES_KEY_BITLEN(kl)); + + /* Set A = IV */ + bcopy(aeskeywrapIV, A, AKW_BLOCK_LEN); + /* For i = 1 to n */ + /* R[i] = P[i] */ + bcopy(input, R, il); + + /* For j = 0 to 5 */ + for (j = 0; j < 6; j++) { + /* For i = 1 to n */ + for (i = 0; i < n; i++) { + dbg(("\n %d\n", (n*j)+i+1)); + pinter(" In ", A, il, R); + /* B = AES(K, A | R[i]) */ + bcopy(&R[i*AKW_BLOCK_LEN], &A[AKW_BLOCK_LEN], AKW_BLOCK_LEN); + aes_block_encrypt((int)AES_ROUNDS(kl), rk, A, B); + + /* R[i] = LSB(64, B) */ + bcopy(&B[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN); + + /* A = MSB(64, B) ^ t where t = (n*j)+i */ + bcopy(&B[0], &A[0], AKW_BLOCK_LEN); + pinter(" Enc ", A, il, R); + A[AKW_BLOCK_LEN-1] ^= ((n*j)+i+1); + pinter(" XorT ", A, il, R); + } + } + /* Set C[0] = A */ + bcopy(A, output, AKW_BLOCK_LEN); + /* For i = 1 to n */ + /* C[i] = R[i] */ + bcopy(R, &output[AKW_BLOCK_LEN], il); + + return (0); +} + +/* aes_unwrap: perform AES-based key unwrap function defined in RFC3394, + * return 0 on success, 1 on error + * input is il bytes + * output is (il-8) bytes + */ +int +BCMROMFN(aes_unwrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output) +{ + uint32 rk[4*(AES_MAXROUNDS+1)]; + uint8 A[AES_BLOCK_SZ]; + uint8 R[AKW_MAX_WRAP_LEN + AKW_BLOCK_LEN]; + uint8 B[AES_BLOCK_SZ]; + size_t ol = il - AKW_BLOCK_LEN; + int n = (int)(ol/AKW_BLOCK_LEN), i, j, k; + + /* validate kl (must be valid AES key length) */ + if ((kl != 16) && (kl != 24) && (kl != 32)) { + dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl)); + return (1); + } + if (il > (AKW_MAX_WRAP_LEN + AKW_BLOCK_LEN)) { + dbg(("aes_unwrap: input length %lu too large\n", (unsigned long)il)); + return (1); + } + if (il % AKW_BLOCK_LEN) { + dbg(("aes_unwrap: input length %lu must be a multiple of block length\n", + (unsigned long)il)); + return (1); + } + + dbg((" Input:\n")); + dbg((" KEK: ")); + for (k = 0; k < (int)kl; k++) + dbg(("%02X", key[k])); + dbg(("\n Data: ")); + for (k = 0; k < (int)il; k++) + dbg(("%02X", input[k])); + dbg(("\n\n Unwrap: \n")); + + rijndaelKeySetupDec(rk, key, (int)AES_KEY_BITLEN(kl)); + + /* Set A = C[0] */ + bcopy(input, A, AKW_BLOCK_LEN); + + /* For i = 1 to n */ + /* R[i] = C[i] */ + bcopy(&input[AKW_BLOCK_LEN], R, ol); + + /* For j = 5 to 0 */ + for (j = 5; j >= 0; j--) { + /* For i = n to 1 */ + for (i = n - 1; i >= 0; i--) { + dbg(("\n %d\n", (n*j)+i+1)); + pinter(" In ", A, ol, R); + + /* B = AES - 1 (K, (A ^ t) | R[i]) where t = n * j + i */ + A[AKW_BLOCK_LEN - 1] ^= ((n*j)+i+1); + pinter(" XorT ", A, ol, R); + + bcopy(&R[i*AKW_BLOCK_LEN], &A[AKW_BLOCK_LEN], AKW_BLOCK_LEN); + aes_block_decrypt((int)AES_ROUNDS(kl), rk, A, B); + + /* A = MSB(64, B) */ + bcopy(&B[0], &A[0], AKW_BLOCK_LEN); + + /* R[i] = LSB(64, B) */ + bcopy(&B[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN); + pinter(" Dec ", A, ol, R); + } + } + if (!bcmp(A, aeskeywrapIV, AKW_BLOCK_LEN)) { + /* For i = 1 to n */ + /* P[i] = R[i] */ + bcopy(R, &output[0], ol); + return 0; + } else { + dbg(("aes_unwrap: IV mismatch in unwrapped data\n")); + return 1; + } +} + +#ifdef BCMAESKEYWRAP_TEST +#include "aeskeywrap_vectors.h" +#define NUM_VECTORS (sizeof(akw_vec)/sizeof(akw_vec[0])) +#define NUM_WRAP_FAIL_VECTORS \ + (sizeof(akw_wrap_fail_vec)/sizeof(akw_wrap_fail_vec[0])) +#define NUM_UNWRAP_FAIL_VECTORS \ + (sizeof(akw_unwrap_fail_vec)/sizeof(akw_unwrap_fail_vec[0])) + +int main(int argc, char **argv) +{ + uint8 output[AKW_MAX_WRAP_LEN+AKW_BLOCK_LEN]; + uint8 input2[AKW_MAX_WRAP_LEN]; + int retv, k, fail = 0; + + for (k = 0; k < NUM_VECTORS; k++) { + retv = aes_wrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il, + akw_vec[k].input, output); + pres("\n AES Wrap: ", akw_vec[k].il+AKW_BLOCK_LEN, output); + + if (retv) { + dbg(("%s: aes_wrap failed\n", *argv)); + fail++; + } + if (bcmp(output, akw_vec[k].ref, akw_vec[k].il+AKW_BLOCK_LEN) != 0) { + dbg(("%s: aes_wrap failed\n", *argv)); + fail++; + } + + retv = aes_unwrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il + AKW_BLOCK_LEN, + output, input2); + pres("\n AES Unwrap: ", akw_vec[k].il, input2); + + if (retv) { + dbg(("%s: aes_unwrap failed\n", *argv)); + fail++; + } + if (bcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) { + dbg(("%s: aes_unwrap failed\n", *argv)); + fail++; + } + } + + for (k = 0; k < NUM_WRAP_FAIL_VECTORS; k++) { + if (!aes_wrap(akw_wrap_fail_vec[k].kl, akw_wrap_fail_vec[k].key, + akw_wrap_fail_vec[k].il, akw_wrap_fail_vec[k].input, output)) { + dbg(("%s: aes_wrap didn't detect failure case\n", *argv)); + fail++; + } + } + + for (k = 0; k < NUM_UNWRAP_FAIL_VECTORS; k++) { + if (!aes_unwrap(akw_unwrap_fail_vec[k].kl, akw_unwrap_fail_vec[k].key, + akw_unwrap_fail_vec[k].il, akw_unwrap_fail_vec[k].input, input2)) { + dbg(("%s: aes_unwrap didn't detect failure case\n", *argv)); + fail++; + } + } + + dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED")); + return (fail); +} +#endif /* BCMAESKEYWRAP_TEST */ diff --git a/release/src-rt/bcmcrypto/aeskeywrap_vectors.h b/release/src-rt/bcmcrypto/aeskeywrap_vectors.h new file mode 100755 index 0000000000..299d4cd580 --- /dev/null +++ b/release/src-rt/bcmcrypto/aeskeywrap_vectors.h @@ -0,0 +1,256 @@ +/* + * aeskeywrap_vectors.h + * AES keywrap test vectors + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: aeskeywrap_vectors.h,v 1.7 2006-06-14 21:08:49 Exp $ + */ + +#include +#include + +/* Test vector data from: + * RFC3394 Advanced Encryption Standard (AES) Key Wrap Algorithm + * Copyright (C) The Internet Society (2002). All Rights Reserved. + */ + +/* 4.1 Wrap 128 bits of Key Data with a 128-bit KEK */ +uint8 key_00[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_00[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_00[] = { + 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, + 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, + 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 + }; + +/* 4.2 Wrap 128 bits of Key Data with a 192-bit KEK */ +uint8 key_01[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + +uint8 input_01[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_01[] = { + 0x96, 0x77, 0x8B, 0x25, 0xAE, 0x6C, 0xA4, 0x35, + 0xF9, 0x2B, 0x5B, 0x97, 0xC0, 0x50, 0xAE, 0xD2, + 0x46, 0x8A, 0xB8, 0xA1, 0x7A, 0xD8, 0x4E, 0x5D + }; + +/* 4.3 Wrap 128 bits of Key Data with a 256-bit KEK */ +uint8 key_02[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_02[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_02[] = { + 0x64, 0xE8, 0xC3, 0xF9, 0xCE, 0x0F, 0x5B, 0xA2, + 0x63, 0xE9, 0x77, 0x79, 0x05, 0x81, 0x8A, 0x2A, + 0x93, 0xC8, 0x19, 0x1E, 0x7D, 0x6E, 0x8A, 0xE7 + }; + +/* 4.4 Wrap 192 bits of Key Data with a 192-bit KEK */ +uint8 key_03[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + +uint8 input_03[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 ref_03[] = { + 0x03, 0x1D, 0x33, 0x26, 0x4E, 0x15, 0xD3, 0x32, + 0x68, 0xF2, 0x4E, 0xC2, 0x60, 0x74, 0x3E, 0xDC, + 0xE1, 0xC6, 0xC7, 0xDD, 0xEE, 0x72, 0x5A, 0x93, + 0x6B, 0xA8, 0x14, 0x91, 0x5C, 0x67, 0x62, 0xD2 + }; + +/* 4.5 Wrap 192 bits of Key Data with a 256-bit KEK */ +uint8 key_04[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_04[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 ref_04[] = { + 0xA8, 0xF9, 0xBC, 0x16, 0x12, 0xC6, 0x8B, 0x3F, + 0xF6, 0xE6, 0xF4, 0xFB, 0xE3, 0x0E, 0x71, 0xE4, + 0x76, 0x9C, 0x8B, 0x80, 0xA3, 0x2C, 0xB8, 0x95, + 0x8C, 0xD5, 0xD1, 0x7D, 0x6B, 0x25, 0x4D, 0xA1 + }; + +/* 4.6 Wrap 256 bits of Key Data with a 256-bit KEK */ +uint8 key_05[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_05[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ref_05[] = { + 0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4, + 0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26, + 0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26, + 0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B, + 0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21 + }; + +/* Test vectors generated at Broadcom */ +/* Wrap 256 bits of Key Data with a 128-bit KEK */ +uint8 key_06[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_06[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ref_06[] = { + 0x11, 0x82, 0x68, 0x40, 0x77, 0x4D, 0x99, 0x3F, + 0xF9, 0xC2, 0xFA, 0x02, 0xCC, 0xA3, 0xCE, 0xA0, + 0xE9, 0x3B, 0x1E, 0x1C, 0xF9, 0x63, 0x61, 0xF9, + 0x3E, 0xA6, 0xDC, 0x2F, 0x34, 0x51, 0x94, 0xE7, + 0xB3, 0x0F, 0x96, 0x4C, 0x79, 0xF9, 0xE6, 0x1D + }; + +/* aes_wrap failure test 1: input too long */ +uint8 key_10[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_10[AKW_MAX_WRAP_LEN+1]; + +uint8 ref_10[] = ""; + +/* aes_wrap failure test 1: input length not multiple of block length */ +uint8 key_11[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_11[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00 + }; + +uint8 ref_11[] = ""; + +/* aes_unwrap failure test 0: input too long */ +uint8 key_20[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_20[AKW_MAX_WRAP_LEN+1]; + +uint8 ref_20[] = ""; + +/* aes_unwrap failure test 1: input length not multiple of block length */ +uint8 key_21[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_21[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00 + }; + +uint8 ref_21[] = ""; + +/* aes_unwrap failure test 2: unwraped data incorrect */ +uint8 key_22[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_22[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_22[] = ""; + + +typedef struct { + int kl; + uint8 *key; + int il; + uint8 *input; + uint8 *ref; +} akw_vector_t; + +#define AKW_VECTOR_ENTRY(x) \ + { sizeof(key_##x), key_##x, sizeof(input_##x), input_##x, ref_##x } + +akw_vector_t akw_vec[] = { + AKW_VECTOR_ENTRY(00), + AKW_VECTOR_ENTRY(01), + AKW_VECTOR_ENTRY(02), + AKW_VECTOR_ENTRY(03), + AKW_VECTOR_ENTRY(04), + AKW_VECTOR_ENTRY(05), + AKW_VECTOR_ENTRY(06) + }; + +akw_vector_t akw_wrap_fail_vec[] = { + AKW_VECTOR_ENTRY(10), + AKW_VECTOR_ENTRY(11) + }; + +akw_vector_t akw_unwrap_fail_vec[] = { + AKW_VECTOR_ENTRY(20), + AKW_VECTOR_ENTRY(21), + AKW_VECTOR_ENTRY(22) + }; diff --git a/release/src-rt/bcmcrypto/prebuilt/.dummy b/release/src-rt/bcmcrypto/bcmccx.c old mode 100644 new mode 100755 similarity index 100% copy from release/src-rt/bcmcrypto/prebuilt/.dummy copy to release/src-rt/bcmcrypto/bcmccx.c diff --git a/release/src-rt/bcmcrypto/bn.c b/release/src-rt/bcmcrypto/bn.c new file mode 100755 index 0000000000..aee01f6aef --- /dev/null +++ b/release/src-rt/bcmcrypto/bn.c @@ -0,0 +1,5661 @@ +/* + * bn.c: Big Number routines. Needed by Diffie Hellman implementation. + * + * Code copied from openssl distribution and + * Modified just enough so that compiles and runs standalone + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: bn.c,v 1.7 2007-10-13 00:50:05 Exp $ + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Includes code written by Lenka Fibikova + * for the OpenSSL project. + */ + +#include +#include +#include +#include +#include +#include +#include "bn_lcl.h" + +#define OPENSSL_malloc malloc +#define OPENSSL_free free +#define OPENSSL_cleanse(buf, size) memset(buf, 0, size) +#define BNerr(a, b) + +static bn_rand_fn_t bn_rand_fn = NULL; + +void +BN_register_RAND(bn_rand_fn_t fn) +{ + bn_rand_fn = fn; +} + +/* r can == a or b */ +int +BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + const BIGNUM *tmp; + int a_neg = a->neg; + + bn_check_top(a); + bn_check_top(b); + + /* a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a_neg ^ b->neg) { + /* only one is negative */ + if (a_neg) { + tmp = a; a = b; b = tmp; + } + + /* we are now a - b */ + + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) return (0); + r->neg = 1; + } else { + if (!BN_usub(r, a, b)) return (0); + r->neg = 0; + } + return (1); + } + + if (!BN_uadd(r, a, b)) return (0); + if (a_neg) /* both are neg */ + r->neg = 1; + else + r->neg = 0; + return (1); +} + +/* unsigned add of b to a, r must be large enough */ +int +BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + register int i; + int max, min; + BN_ULONG *ap, *bp, *rp, carry, t1; + const BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) { + tmp = a; a = b; b = tmp; + } + max = a->top; + min = b->top; + + if (bn_wexpand(r, max+1) == NULL) + return (0); + + r->top = max; + + + ap = a->d; + bp = b->d; + rp = r->d; + carry = 0; + + carry = bn_add_words(rp, ap, bp, min); + rp += min; + ap += min; + bp += min; + i = min; + + if (carry) { + while (i < max) { + i++; + t1 = *(ap++); + if ((*(rp++) = (t1+1)&BN_MASK2) >= t1) { + carry = 0; + break; + } + } + if ((i >= max) && carry) { + *(rp++) = 1; + r->top++; + } + } + if (rp != ap) { + for (; i < max; i++) + *(rp++) = *(ap++); + } + /* memcpy(rp, ap, sizeof(*ap)*(max-i)); */ + r->neg = 0; + return (1); +} + +/* unsigned subtraction of b from a, a must be larger than b. */ +int +BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max, min; + register BN_ULONG t1, t2, *ap, *bp, *rp; + int i, carry; +#if defined(IRIX_CC_BUG) && !defined(LINT) + int dummy; +#endif + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) /* hmm... should not be happening */ { + BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3); + return (0); + } + + max = a->top; + min = b->top; + if (bn_wexpand(r, max) == NULL) return (0); + + ap = a->d; + bp = b->d; + rp = r->d; + + carry = 0; + for (i = 0; i < min; i++) { + t1 = *(ap++); + t2 = *(bp++); + if (carry) { + carry = (t1 <= t2); + t1 = (t1-t2-1)&BN_MASK2; + } + else { + carry = (t1 < t2); + t1 = (t1-t2)&BN_MASK2; + } +#if defined(IRIX_CC_BUG) && !defined(LINT) + dummy = t1; +#endif + *(rp++) = t1&BN_MASK2; + } + if (carry) /* subtracted */ { + while (i < max) { + i++; + t1 = *(ap++); + t2 = (t1-1)&BN_MASK2; + *(rp++) = t2; + if (t1 > t2) break; + } + } + if (rp != ap) { + for (;;) { + if (i++ >= max) break; + rp[0] = ap[0]; + if (i++ >= max) break; + rp[1] = ap[1]; + if (i++ >= max) break; + rp[2] = ap[2]; + if (i++ >= max) break; + rp[3] = ap[3]; + rp += 4; + ap += 4; + } + } + + r->top = max; + r->neg = 0; + bn_fix_top(r); + return (1); +} + +int +BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max; + int add = 0, neg = 0; + const BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) { + if (b->neg) { tmp = a; a = b; b = tmp; } + else { add = 1; neg = 1; } + } + else { + if (b->neg) { add = 1; neg = 0; } + } + + if (add) { + if (!BN_uadd(r, a, b)) return (0); + r->neg = neg; + return (1); + } + + /* We are actually doing a - b :-) */ + + max = (a->top > b->top)?a->top:b->top; + if (bn_wexpand(r, max) == NULL) return (0); + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) return (0); + r->neg = 1; + } + else { + if (!BN_usub(r, a, b)) return (0); + r->neg = 0; + } + return (1); +} + + +#if defined(BN_LLONG) || defined(BN_UMULT_HIGH) + +BN_ULONG +bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) return (c1); + + while (num&~3) { + mul_add(rp[0], ap[0], w, c1); + mul_add(rp[1], ap[1], w, c1); + mul_add(rp[2], ap[2], w, c1); + mul_add(rp[3], ap[3], w, c1); + ap += 4; rp += 4; num -= 4; + } + if (num) { + mul_add(rp[0], ap[0], w, c1); if (--num == 0) return c1; + mul_add(rp[1], ap[1], w, c1); if (--num == 0) return c1; + mul_add(rp[2], ap[2], w, c1); return c1; + } + + return (c1); +} + +BN_ULONG +bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) return (c1); + + while (num&~3) { + mul(rp[0], ap[0], w, c1); + mul(rp[1], ap[1], w, c1); + mul(rp[2], ap[2], w, c1); + mul(rp[3], ap[3], w, c1); + ap += 4; rp += 4; num -= 4; + } + if (num) { + mul(rp[0], ap[0], w, c1); if (--num == 0) return c1; + mul(rp[1], ap[1], w, c1); if (--num == 0) return c1; + mul(rp[2], ap[2], w, c1); + } + return (c1); +} + +void +bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + assert(n >= 0); + if (n <= 0) return; + while (n & ~3) { + sqr(r[0], r[1], a[0]); + sqr(r[2], r[3], a[1]); + sqr(r[4], r[5], a[2]); + sqr(r[6], r[7], a[3]); + a += 4; r += 8; n -= 4; + } + if (n) { + sqr(r[0], r[1], a[0]); if (--n == 0) return; + sqr(r[2], r[3], a[1]); if (--n == 0) return; + sqr(r[4], r[5], a[2]); + } +} + +#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */ + +BN_ULONG +bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c = 0; + BN_ULONG bl, bh; + + assert(num >= 0); + if (num <= 0) return ((BN_ULONG)0); + + bl = LBITS(w); + bh = HBITS(w); + + for (;;) { + mul_add(rp[0], ap[0], bl, bh, c); + if (--num == 0) break; + mul_add(rp[1], ap[1], bl, bh, c); + if (--num == 0) break; + mul_add(rp[2], ap[2], bl, bh, c); + if (--num == 0) break; + mul_add(rp[3], ap[3], bl, bh, c); + if (--num == 0) break; + ap += 4; + rp += 4; + } + return (c); +} + +BN_ULONG +bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG carry = 0; + BN_ULONG bl, bh; + + assert(num >= 0); + if (num <= 0) return ((BN_ULONG)0); + + bl = LBITS(w); + bh = HBITS(w); + + for (;;) { + mul(rp[0], ap[0], bl, bh, carry); + if (--num == 0) break; + mul(rp[1], ap[1], bl, bh, carry); + if (--num == 0) break; + mul(rp[2], ap[2], bl, bh, carry); + if (--num == 0) break; + mul(rp[3], ap[3], bl, bh, carry); + if (--num == 0) break; + ap += 4; + rp += 4; + } + return (carry); +} + +void +bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + assert(n >= 0); + if (n <= 0) return; + for (;;) { + sqr64(r[0], r[1], a[0]); + if (--n == 0) break; + + sqr64(r[2], r[3], a[1]); + if (--n == 0) break; + + sqr64(r[4], r[5], a[2]); + if (--n == 0) break; + + sqr64(r[6], r[7], a[3]); + if (--n == 0) break; + + a += 4; + r += 8; + } +} + +#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */ + +#if defined(BN_LLONG) && defined(BN_DIV2W) + +BN_ULONG +bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + return ((BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2)|l) / (BN_ULLONG)d)); +} + +#else + +/* Divide h, l by d and return the result. */ +/* I need to test this some more :-( */ +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + BN_ULONG dh, dl, q, ret = 0, th, tl, t; + int i, count = 2; + + if (d == 0) return (BN_MASK2); + + i = BN_num_bits_word(d); + assert((i == BN_BITS2) || (h > (BN_ULONG)1 << i)); + + i = BN_BITS2-i; + if (h >= d) h -= d; + + if (i) { + d <<= i; + h = (h << i) | (l >> (BN_BITS2 - i)); + l <<= i; + } + dh = (d&BN_MASK2h) >> BN_BITS4; + dl = (d&BN_MASK2l); + for (;;) { + if ((h>>BN_BITS4) == dh) + q = BN_MASK2l; + else + q = h/dh; + + th = q*dh; + tl = dl*q; + for (;;) { + t = h-th; + if ((t&BN_MASK2h) || + ((tl) <= ((t << BN_BITS4) | + ((l & BN_MASK2h) >> BN_BITS4)))) + break; + q--; + th -= dh; + tl -= dl; + } + t = (tl >> BN_BITS4); + tl = (tl << BN_BITS4) & BN_MASK2h; + th += t; + + if (l < tl) th++; + l -= tl; + if (h < th) { + h += d; + q--; + } + h -= th; + + if (--count == 0) break; + + ret = q << BN_BITS4; + h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2; + l = (l & BN_MASK2l) << BN_BITS4; + } + ret |= q; + return (ret); +} +#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */ + +#ifdef BN_LLONG +BN_ULONG +bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + BN_ULLONG ll = 0; + + assert(n >= 0); + if (n <= 0) return ((BN_ULONG)0); + + for (;;) { + ll += (BN_ULLONG)a[0]+b[0]; + r[0] = (BN_ULONG)ll&BN_MASK2; + ll >>= BN_BITS2; + if (--n <= 0) break; + + ll += (BN_ULLONG)a[1]+b[1]; + r[1] = (BN_ULONG)ll&BN_MASK2; + ll >>= BN_BITS2; + if (--n <= 0) break; + + ll += (BN_ULLONG)a[2]+b[2]; + r[2] = (BN_ULONG)ll&BN_MASK2; + ll >>= BN_BITS2; + if (--n <= 0) break; + + ll += (BN_ULLONG)a[3]+b[3]; + r[3] = (BN_ULONG)ll&BN_MASK2; + ll >>= BN_BITS2; + if (--n <= 0) break; + + a += 4; + b += 4; + r += 4; + } + return ((BN_ULONG)ll); +} + +#else /* !BN_LLONG */ + +BN_ULONG +bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + BN_ULONG c, l, t; + + assert(n >= 0); + if (n <= 0) return ((BN_ULONG)0); + + c = 0; + for (;;) { + t = a[0]; + t = (t+c)&BN_MASK2; + c = (t < c); + l = (t+b[0])&BN_MASK2; + c += (l < t); + r[0] = l; + if (--n <= 0) break; + + t = a[1]; + t = (t+c)&BN_MASK2; + c = (t < c); + l = (t+b[1])&BN_MASK2; + c += (l < t); + r[1] = l; + if (--n <= 0) break; + + t = a[2]; + t = (t+c)&BN_MASK2; + c = (t < c); + l = (t+b[2])&BN_MASK2; + c += (l < t); + r[2] = l; + if (--n <= 0) break; + + t = a[3]; + t = (t+c)&BN_MASK2; + c = (t < c); + l = (t+b[3])&BN_MASK2; + c += (l < t); + r[3] = l; + if (--n <= 0) break; + + a += 4; + b += 4; + r += 4; + } + return ((BN_ULONG)c); +} +#endif /* !BN_LLONG */ + +BN_ULONG +bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + BN_ULONG t1, t2; + int c = 0; + + assert(n >= 0); + if (n <= 0) return ((BN_ULONG)0); + + for (;;) { + t1 = a[0]; t2 = b[0]; + r[0] = (t1-t2-c)&BN_MASK2; + if (t1 != t2) c = (t1 < t2); + if (--n <= 0) break; + + t1 = a[1]; t2 = b[1]; + r[1] = (t1-t2-c)&BN_MASK2; + if (t1 != t2) c = (t1 < t2); + if (--n <= 0) break; + + t1 = a[2]; t2 = b[2]; + r[2] = (t1-t2-c)&BN_MASK2; + if (t1 != t2) c = (t1 < t2); + if (--n <= 0) break; + + t1 = a[3]; t2 = b[3]; + r[3] = (t1-t2-c)&BN_MASK2; + if (t1 != t2) c = (t1 < t2); + if (--n <= 0) break; + + a += 4; + b += 4; + r += 4; + } + return (c); +} + +#ifdef BN_MUL_COMBA + +#undef bn_mul_comba8 +#undef bn_mul_comba4 +#undef bn_sqr_comba8 +#undef bn_sqr_comba4 + +/* mul_add_c(a, b, c0, c1, c2) -- c += a*b for three word number c = (c2, c1, c0) */ +/* mul_add_c2(a, b, c0, c1, c2) -- c += 2*a*b for three word number c = (c2, c1, c0) */ +/* sqr_add_c(a, i, c0, c1, c2) -- c += a[i]^2 for three word number c = (c2, c1, c0) */ +/* sqr_add_c2(a, i, c0, c1, c2) -- c += 2*a[i]*a[j] for three word number c = (c2, c1, c0) */ + +#ifdef BN_LLONG +#define mul_add_c(a, b, c0, c1, c2) \ + t = (BN_ULLONG)a * b; \ + t1 = (BN_ULONG)Lw(t); \ + t2 = (BN_ULONG)Hw(t); \ + c0 = (c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1 = (c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a, b, c0, c1, c2) \ + t = (BN_ULLONG)a * b; \ + tt = (t + t) & BN_MASK; \ + if (tt < t) c2++; \ + t1 = (BN_ULONG)Lw(tt); \ + t2 = (BN_ULONG)Hw(tt); \ + c0 = (c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) c2++; \ + c1 = (c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a, i, c0, c1, c2) \ + t = (BN_ULLONG)a[i]*a[i]; \ + t1 = (BN_ULONG)Lw(t); \ + t2 = (BN_ULONG)Hw(t); \ + c0 = (c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1 = (c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a, i, j, c0, c1, c2) \ + mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +#elif defined(BN_UMULT_HIGH) + +#define mul_add_c(a, b, c0, c1, c2) { \ + BN_ULONG ta = (a), tb = (b); \ + t1 = ta * tb; \ + t2 = BN_UMULT_HIGH(ta, tb); \ + c0 += t1; t2 += (c0 < t1) ? 1 : 0; \ + c1 += t2; c2 += (c1 < t2) ? 1 : 0; \ +} + +#define mul_add_c2(a, b, c0, c1, c2) { \ + BN_ULONG ta = (a), tb = (b), t0; \ + t1 = BN_UMULT_HIGH(ta, tb); \ + t0 = ta * tb; \ + t2 = t1 + t1; c2 += (t2 < t1) ? 1 : 0; \ + t1 = t0 + t0; t2 += (t1 < t0) ? 1 : 0; \ + c0 += t1; t2 += (c0 < t1) ? 1 : 0; \ + c1 += t2; c2 += (c1 < t2) ? 1 : 0; \ +} + +#define sqr_add_c(a, i, c0, c1, c2) { \ + BN_ULONG ta = (a)[i]; \ + t1 = ta * ta; \ + t2 = BN_UMULT_HIGH(ta, ta); \ + c0 += t1; t2 += (c0 < t1) ? 1 : 0; \ + c1 += t2; c2 += (c1 < t2) ? 1 : 0; \ +} + +#define sqr_add_c2(a, i, j, c0, c1, c2) \ + mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +#else /* !BN_LLONG */ + +#define mul_add_c(a, b, c0, c1, c2) \ + t1 = LBITS(a); t2 = HBITS(a); \ + bl = LBITS(b); bh = HBITS(b); \ + mul64(t1, t2, bl, bh); \ + c0 = (c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1 = (c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a, b, c0, c1, c2) \ + t1 = LBITS(a); t2 = HBITS(a); \ + bl = LBITS(b); bh = HBITS(b); \ + mul64(t1, t2, bl, bh); \ + if (t2 & BN_TBIT) c2++; \ + t2 = (t2+t2) & BN_MASK2; \ + if (t1 & BN_TBIT) t2++; \ + t1 = (t1+t1) & BN_MASK2; \ + c0 = (c0+t1) & BN_MASK2; \ + if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) c2++; \ + c1 = (c1+t2) & BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a, i, c0, c1, c2) \ + sqr64(t1, t2, (a)[i]); \ + c0 = (c0+t1) & BN_MASK2; if ((c0) < t1) t2++; \ + c1 = (c1+t2) & BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a, i, j, c0, c1, c2) \ + mul_add_c2((a)[i], (a)[j], c0, c1, c2) +#endif /* !BN_LLONG */ + +void +bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl, bh; +#endif + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[4], b[0], c2, c3, c1); + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + mul_add_c(a[0], b[4], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[0], b[5], c3, c1, c2); + mul_add_c(a[1], b[4], c3, c1, c2); + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + mul_add_c(a[4], b[1], c3, c1, c2); + mul_add_c(a[5], b[0], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[6], b[0], c1, c2, c3); + mul_add_c(a[5], b[1], c1, c2, c3); + mul_add_c(a[4], b[2], c1, c2, c3); + mul_add_c(a[3], b[3], c1, c2, c3); + mul_add_c(a[2], b[4], c1, c2, c3); + mul_add_c(a[1], b[5], c1, c2, c3); + mul_add_c(a[0], b[6], c1, c2, c3); + r[6] = c1; + c1 = 0; + mul_add_c(a[0], b[7], c2, c3, c1); + mul_add_c(a[1], b[6], c2, c3, c1); + mul_add_c(a[2], b[5], c2, c3, c1); + mul_add_c(a[3], b[4], c2, c3, c1); + mul_add_c(a[4], b[3], c2, c3, c1); + mul_add_c(a[5], b[2], c2, c3, c1); + mul_add_c(a[6], b[1], c2, c3, c1); + mul_add_c(a[7], b[0], c2, c3, c1); + r[7] = c2; + c2 = 0; + mul_add_c(a[7], b[1], c3, c1, c2); + mul_add_c(a[6], b[2], c3, c1, c2); + mul_add_c(a[5], b[3], c3, c1, c2); + mul_add_c(a[4], b[4], c3, c1, c2); + mul_add_c(a[3], b[5], c3, c1, c2); + mul_add_c(a[2], b[6], c3, c1, c2); + mul_add_c(a[1], b[7], c3, c1, c2); + r[8] = c3; + c3 = 0; + mul_add_c(a[2], b[7], c1, c2, c3); + mul_add_c(a[3], b[6], c1, c2, c3); + mul_add_c(a[4], b[5], c1, c2, c3); + mul_add_c(a[5], b[4], c1, c2, c3); + mul_add_c(a[6], b[3], c1, c2, c3); + mul_add_c(a[7], b[2], c1, c2, c3); + r[9] = c1; + c1 = 0; + mul_add_c(a[7], b[3], c2, c3, c1); + mul_add_c(a[6], b[4], c2, c3, c1); + mul_add_c(a[5], b[5], c2, c3, c1); + mul_add_c(a[4], b[6], c2, c3, c1); + mul_add_c(a[3], b[7], c2, c3, c1); + r[10] = c2; + c2 = 0; + mul_add_c(a[4], b[7], c3, c1, c2); + mul_add_c(a[5], b[6], c3, c1, c2); + mul_add_c(a[6], b[5], c3, c1, c2); + mul_add_c(a[7], b[4], c3, c1, c2); + r[11] = c3; + c3 = 0; + mul_add_c(a[7], b[5], c1, c2, c3); + mul_add_c(a[6], b[6], c1, c2, c3); + mul_add_c(a[5], b[7], c1, c2, c3); + r[12] = c1; + c1 = 0; + mul_add_c(a[6], b[7], c2, c3, c1); + mul_add_c(a[7], b[6], c2, c3, c1); + r[13] = c2; + c2 = 0; + mul_add_c(a[7], b[7], c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl, bh; +#endif + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[3], b[3], c1, c2, c3); + r[6] = c1; + r[7] = c2; +} + +void +bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) +{ +#ifdef BN_LLONG + BN_ULLONG t, tt; +#else + BN_ULONG bl, bh; +#endif + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + sqr_add_c2(a, 4, 0, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 5, 0, c3, c1, c2); + sqr_add_c2(a, 4, 1, c3, c1, c2); + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + sqr_add_c2(a, 4, 2, c1, c2, c3); + sqr_add_c2(a, 5, 1, c1, c2, c3); + sqr_add_c2(a, 6, 0, c1, c2, c3); + r[6] = c1; + c1 = 0; + sqr_add_c2(a, 7, 0, c2, c3, c1); + sqr_add_c2(a, 6, 1, c2, c3, c1); + sqr_add_c2(a, 5, 2, c2, c3, c1); + sqr_add_c2(a, 4, 3, c2, c3, c1); + r[7] = c2; + c2 = 0; + sqr_add_c(a, 4, c3, c1, c2); + sqr_add_c2(a, 5, 3, c3, c1, c2); + sqr_add_c2(a, 6, 2, c3, c1, c2); + sqr_add_c2(a, 7, 1, c3, c1, c2); + r[8] = c3; + c3 = 0; + sqr_add_c2(a, 7, 2, c1, c2, c3); + sqr_add_c2(a, 6, 3, c1, c2, c3); + sqr_add_c2(a, 5, 4, c1, c2, c3); + r[9] = c1; + c1 = 0; + sqr_add_c(a, 5, c2, c3, c1); + sqr_add_c2(a, 6, 4, c2, c3, c1); + sqr_add_c2(a, 7, 3, c2, c3, c1); + r[10] = c2; + c2 = 0; + sqr_add_c2(a, 7, 4, c3, c1, c2); + sqr_add_c2(a, 6, 5, c3, c1, c2); + r[11] = c3; + c3 = 0; + sqr_add_c(a, 6, c1, c2, c3); + sqr_add_c2(a, 7, 5, c1, c2, c3); + r[12] = c1; + c1 = 0; + sqr_add_c2(a, 7, 6, c2, c3, c1); + r[13] = c2; + c2 = 0; + sqr_add_c(a, 7, c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void +bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) +{ +#ifdef BN_LLONG + BN_ULLONG t, tt; +#else + BN_ULONG bl, bh; +#endif + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + r[6] = c1; + r[7] = c2; +} +#else /* !BN_MUL_COMBA */ + +/* hmm... is it faster just to do a multiply? */ +#undef bn_sqr_comba4 +void +bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) +{ + BN_ULONG t[8]; + bn_sqr_normal(r, a, 4, t); +} + +#undef bn_sqr_comba8 +void +bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) +{ + BN_ULONG t[16]; + bn_sqr_normal(r, a, 8, t); +} + +void +bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + r[4] = bn_mul_words(&(r[0]), a, 4, b[0]); + r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]); + r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]); + r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]); +} + +void +bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + r[ 8] = bn_mul_words(&(r[0]), a, 8, b[0]); + r[ 9] = bn_mul_add_words(&(r[1]), a, 8, b[1]); + r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]); + r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]); + r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]); + r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]); + r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]); + r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]); +} + +#endif /* !BN_MUL_COMBA */ + + +BN_CTX * +BN_CTX_new(void) +{ + BN_CTX *ret; + + ret = (BN_CTX *)OPENSSL_malloc(sizeof(BN_CTX)); + if (ret == NULL) { + BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE); + return (NULL); + } + + BN_CTX_init(ret); + ret->flags = BN_FLG_MALLOCED; + return (ret); +} + +void +BN_CTX_init(BN_CTX *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void +BN_CTX_free(BN_CTX *ctx) +{ + int i; + + if (ctx == NULL) return; + assert(ctx->depth == 0); + + for (i = 0; i < BN_CTX_NUM; i++) + BN_clear_free(&(ctx->bn[i])); + if (ctx->flags & BN_FLG_MALLOCED) + OPENSSL_free(ctx); +} + +void +BN_CTX_start(BN_CTX *ctx) +{ + if (ctx->depth < BN_CTX_NUM_POS) + ctx->pos[ctx->depth] = ctx->tos; + ctx->depth++; +} + + +BIGNUM * +BN_CTX_get(BN_CTX *ctx) +{ + /* Note: If BN_CTX_get is ever changed to allocate BIGNUMs dynamically, + * make sure that if BN_CTX_get fails once it will return NULL again + * until BN_CTX_end is called. (This is so that callers have to check + * only the last return value.) + */ + if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM) { + if (!ctx->too_many) { + BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + /* disable error code until BN_CTX_end is called: */ + ctx->too_many = 1; + } + return NULL; + } + return (&(ctx->bn[ctx->tos++])); +} + +void +BN_CTX_end(BN_CTX *ctx) +{ + if (ctx == NULL) return; + assert(ctx->depth > 0); + if (ctx->depth == 0) { + /* should never happen, but we can tolerate it if not in + * debug mode (could be a 'goto err' in the calling function + * before BN_CTX_start was reached) + */ + BN_CTX_start(ctx); + } + ctx->too_many = 0; + ctx->depth--; + if (ctx->depth < BN_CTX_NUM_POS) + ctx->tos = ctx->pos[ctx->depth]; +} + +/* The old slow way */ + +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) \ + && !defined(BN_DIV3W) +#if defined(__GNUC__) && __GNUC__ >= 2 +#if defined(__i386) || defined(__i386__) +/* + * There were two reasons for implementing this template: + * - GNU C generates a call to a function (__udivdi3 to be exact) + * in reply to ((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0 (I fail to + * understand why...); + * - divl doesn't only calculate quotient, but also leaves + * remainder in %edx which we can definitely use here:-) + * + * + */ +#define bn_div_words(n0, n1, d0) \ + ({ asm volatile("divl %4" \ + : " = a"(q), " = d"(rem) \ + : "a"(n1), "d"(n0), "g"(d0) \ + : "cc"); \ + q; \ + }) +#define REMAINDER_IS_ALREADY_CALCULATED +#elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG) +/* + * Same story here, but it's 128-bit by 64-bit division. Wow! + * + */ +#define bn_div_words(n0, n1, d0) \ + ({ asm volatile("divq %4" \ + : " = a"(q), " = d"(rem) \ + : "a"(n1), "d"(n0), "g"(d0) \ + : "cc"); \ + q; \ + }) +#define REMAINDER_IS_ALREADY_CALCULATED +#endif /* __ */ +#endif /* __GNUC__ */ +#endif /* OPENSSL_NO_ASM */ + + +/* BN_div computes dv : = num / divisor, rounding towards zero, and sets up + * rm such that dv*divisor + rm = num holds. + * Thus: + * dv->neg == num->neg ^ divisor->neg (unless the result is zero) + * rm->neg == num->neg (unless the remainder is zero) + * If 'dv' or 'rm' is NULL, the respective value is not returned. + */ +int +BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) +{ + int norm_shift, i, j, loop; + BIGNUM *tmp, wnum, *snum, *sdiv, *res; + BN_ULONG *resp, *wnump; + BN_ULONG d0, d1; + int num_n, div_n; + + bn_check_top(num); + bn_check_top(divisor); + + if (BN_is_zero(divisor)) { + BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + return (0); + } + + if (BN_ucmp(num, divisor) < 0) { + if (rm != NULL) { if (BN_copy(rm, num) == NULL) return (0); } + if (dv != NULL) BN_zero(dv); + return (1); + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + snum = BN_CTX_get(ctx); + sdiv = BN_CTX_get(ctx); + if (dv == NULL) + res = BN_CTX_get(ctx); + else res = dv; + if (sdiv == NULL || res == NULL) goto err; + tmp->neg = 0; + + /* First we normalise the numbers */ + norm_shift = BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); + if (!(BN_lshift(sdiv, divisor, norm_shift))) goto err; + sdiv->neg = 0; + norm_shift += BN_BITS2; + if (!(BN_lshift(snum, num, norm_shift))) goto err; + snum->neg = 0; + div_n = sdiv->top; + num_n = snum->top; + loop = num_n-div_n; + + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided + */ + BN_init(&wnum); + wnum.d = &(snum->d[loop]); + wnum.top = div_n; + wnum.dmax = snum->dmax+1; /* a bit of a lie */ + + /* Get the top 2 words of sdiv */ + /* i = sdiv->top; */ + d0 = sdiv->d[div_n-1]; + d1 = (div_n == 1)?0:sdiv->d[div_n-2]; + + /* pointer to the 'top' of snum */ + wnump = &(snum->d[num_n-1]); + + /* Setup to 'res' */ + res->neg = (num->neg^divisor->neg); + if (!bn_wexpand(res, (loop+1))) goto err; + res->top = loop; + resp = &(res->d[loop-1]); + + /* space for temp */ + if (!bn_wexpand(tmp, (div_n+1))) goto err; + + if (BN_ucmp(&wnum, sdiv) >= 0) { + if (!BN_usub(&wnum, &wnum, sdiv)) goto err; + *resp = 1; + res->d[res->top-1] = 1; + } else + res->top--; + if (res->top == 0) + res->neg = 0; + resp--; + + for (i = 0; i < loop - 1; i++) { + BN_ULONG q, l0; +#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) + BN_ULONG bn_div_3_words(BN_ULONG*, BN_ULONG, BN_ULONG); + q = bn_div_3_words(wnump, d1, d0); +#else + BN_ULONG n0, n1, rem = 0; + + n0 = wnump[0]; + n1 = wnump[-1]; + if (n0 == d0) + q = BN_MASK2; + else /* n0 < d0 */ { +#ifdef BN_LLONG + BN_ULLONG t2; + +#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) + q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0); +#else + q = bn_div_words(n0, n1, d0); +#ifdef BN_DEBUG_LEVITTE + fprintf(stderr, "DEBUG: bn_div_words(0x%08X, 0x%08X, 0x%08X) -> 0x%08X\n", + n0, n1, d0, q); +#endif /* BN_DEBUG_LEVITTE */ +#endif /* BN_LLONG && BN_DIV2W && !bn_div_words */ + +#ifndef REMAINDER_IS_ALREADY_CALCULATED + /* + * rem doesn't have to be BN_ULLONG. The least we + * know it's less that d0, isn't it? + */ + rem = (n1 - q * d0) & BN_MASK2; +#endif /* !REMAINDER_IS_ALREADY_CALCULATED */ + t2 = (BN_ULLONG)d1 * q; + + for (;;) { + if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) + break; + q--; + rem += d0; + if (rem < d0) break; /* don't let rem overflow */ + t2 -= d1; + } +#else /* !BN_LLONG */ + BN_ULONG t2l, t2h, ql, qh; + + q = bn_div_words(n0, n1, d0); +#ifdef BN_DEBUG_LEVITTE + fprintf(stderr, "DEBUG: bn_div_words(0x%08X, 0x%08X, 0x%08X) -> 0x%08X\n", + n0, n1, d0, q); +#endif +#ifndef REMAINDER_IS_ALREADY_CALCULATED + rem = (n1 - q * d0) & BN_MASK2; +#endif + +#if defined(BN_UMULT_LOHI) + BN_UMULT_LOHI(t2l, t2h, d1, q); +#elif defined(BN_UMULT_HIGH) + t2l = d1 * q; + t2h = BN_UMULT_HIGH(d1, q); +#else + t2l = LBITS(d1); t2h = HBITS(d1); + ql = LBITS(q); qh = HBITS(q); + mul64(t2l, t2h, ql, qh); /* t2 = (BN_ULLONG)d1 * q; */ +#endif + + for (;;) { + if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) + break; + q--; + rem += d0; + if (rem < d0) break; /* don't let rem overflow */ + if (t2l < d1) + t2h--; + t2l -= d1; + } +#endif /* !BN_LLONG */ + } +#endif /* !BN_DIV3W */ + + l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); + wnum.d--; wnum.top++; + tmp->d[div_n] = l0; + for (j = div_n + 1; j > 0; j--) + if (tmp->d[j - 1]) break; + tmp->top = j; + + j = wnum.top; + if (!BN_sub(&wnum, &wnum, tmp)) goto err; + + snum->top = snum->top + wnum.top - j; + + if (wnum.neg) { + q--; + j = wnum.top; + if (!BN_add(&wnum, &wnum, sdiv)) goto err; + snum->top += wnum.top - j; + } + *(resp--) = q; + wnump--; + } + if (rm != NULL) { + /* Keep a copy of the neg flag in num because if rm == num + * BN_rshift() will overwrite it. + */ + int neg = num->neg; + BN_rshift(rm, snum, norm_shift); + if (!BN_is_zero(rm)) + rm->neg = neg; + } + BN_CTX_end(ctx); + return (1); +err: + BN_CTX_end(ctx); + return (0); +} + + + +#define TABLE_SIZE 32 + +#ifdef NOT_NEEDED_FOR_DH +/* this one works - simple but works */ +int +BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + int i, bits, ret = 0; + BIGNUM *v, *rr; + + BN_CTX_start(ctx); + if ((r == a) || (r == p)) + rr = BN_CTX_get(ctx); + else + rr = r; + if ((v = BN_CTX_get(ctx)) == NULL) goto err; + + if (BN_copy(v, a) == NULL) goto err; + bits = BN_num_bits(p); + + if (BN_is_odd(p)) { + if (BN_copy(rr, a) == NULL) + goto err; + } else { + if (!BN_one(rr)) + goto err; + } + + for (i = 1; i < bits; i++) { + if (!BN_sqr(v, v, ctx)) goto err; + if (BN_is_bit_set(p, i)) { + if (!BN_mul(rr, rr, v, ctx)) goto err; + } + } + ret = 1; +err: + if (r != rr) BN_copy(r, rr); + BN_CTX_end(ctx); + return (ret); +} + +int +BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) +{ + int ret; + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + /* For even modulus m = 2^k*m_odd, it might make sense to compute + * a^p mod m_odd and a^p mod 2^k separately (with Montgomery + * exponentiation for the odd part), using appropriate exponent + * reductions, and combine the results using the CRT. + * + * For now, we use Montgomery only if the modulus is odd; otherwise, + * exponentiation using the reciprocal-based quick remaindering + * algorithm is used. + * + * (Timing obtained with expspeed.c [computations a^p mod m + * where a, p, m are of the same length: 256, 512, 1024, 2048, + * 4096, 8192 bits], compared to the running time of the + * standard algorithm: + * + * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration] + * 55 .. 77 % [UltraSparc processor, but + * debug-solaris-sparcv8-gcc conf.] + * + * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration] + * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc] + * + * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont + * at 2048 and more bits, but at 512 and 1024 bits, it was + * slower even than the standard algorithm! + * + * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations] + * should be obtained when the new Montgomery reduction code + * has been integrated into OpenSSL.) + */ + +#define MONT_MUL_MOD +#define MONT_EXP_WORD +#define RECP_MUL_MOD + +#ifdef MONT_MUL_MOD + /* I have finally been able to take out this pre-condition of + * the top bit being set. It was caused by an error in BN_div + * with negatives. There was also another problem when for a^b%m + * a >= m. eay 07-May-97 + */ +/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */ + + if (BN_is_odd(m)) { +#ifdef MONT_EXP_WORD + if (a->top == 1 && !a->neg) { + BN_ULONG A = a->d[0]; + ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL); + } else +#endif + ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL); + } else +#endif /* MONT_MUL_MOD */ +#ifdef RECP_MUL_MOD + { + ret = BN_mod_exp_recp(r, a, p, m, ctx); + } +#else + { + ret = BN_mod_exp_simple(r, a, p, m, ctx); + } +#endif + + return (ret); +} + + +int +BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1, ts = 0; + BIGNUM *aa; + BIGNUM val[TABLE_SIZE]; + BN_RECP_CTX recp; + + bits = BN_num_bits(p); + + if (bits == 0) { + ret = BN_one(r); + return ret; + } + + BN_CTX_start(ctx); + if ((aa = BN_CTX_get(ctx)) == NULL) goto err; + + BN_RECP_CTX_init(&recp); + if (m->neg) { + /* ignore sign of 'm' */ + if (!BN_copy(aa, m)) goto err; + aa->neg = 0; + if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) goto err; + } else { + if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) goto err; + } + + BN_init(&(val[0])); + ts = 1; + + if (!BN_nnmod(&(val[0]), a, m, ctx)) goto err; /* 1 */ + if (BN_is_zero(&(val[0]))) { + ret = BN_zero(r); + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul_reciprocal(aa, &(val[0]), &(val[0]), &recp, ctx)) + goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + BN_init(&val[i]); + if (!BN_mod_mul_reciprocal(&(val[i]), &(val[i - 1]), aa, &recp, ctx)) + goto err; + } + ts = i; + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. + */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + if (wstart == 0) break; + wstart--; + continue; + } + /* We now have wstart on a 'set' bit, we now need to work out + * how bit a window to do. To do this we need to scan + * forward until the last set bit before the end of the + * window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) break; + if (BN_is_bit_set(p, wstart-i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend+1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_reciprocal(r, r, &(val[wvalue >> 1]), &recp, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend+1; + wvalue = 0; + start = 0; + if (wstart < 0) break; + } + ret = 1; +err: + BN_CTX_end(ctx); + for (i = 0; i < ts; i++) + BN_clear_free(&(val[i])); + BN_RECP_CTX_free(&recp); + return (ret); +} +#endif /* NOT_NEEDED_FOR_DH */ + + +int +BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1, ts = 0; + BIGNUM *d, *r; + const BIGNUM *aa; + BIGNUM val[TABLE_SIZE]; + BN_MONT_CTX *mont = NULL; + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + if (!(m->d[0] & 1)) { + BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + return (0); + } + bits = BN_num_bits(p); + if (bits == 0) { + ret = BN_one(rr); + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + if (d == NULL || r == NULL) goto err; + + /* If this is not done, things will break in the montgomery part */ + + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) goto err; + } + + BN_init(&val[0]); + ts = 1; + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_nnmod(&(val[0]), a, m, ctx)) + goto err; + aa = &(val[0]); + } else + aa = a; + if (BN_is_zero(aa)) { + ret = BN_zero(rr); + goto err; + } + if (!BN_to_montgomery(&(val[0]), aa, mont, ctx)) goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul_montgomery(d, &(val[0]), &(val[0]), mont, ctx)) goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + BN_init(&(val[i])); + if (!BN_mod_mul_montgomery(&(val[i]), &(val[i - 1]), d, mont, ctx)) + goto err; + } + ts = i; + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. + */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits-1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) goto err; + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + if (wstart == 0) break; + wstart--; + continue; + } + /* We now have wstart on a 'set' bit, we now need to work out + * how bit a window to do. To do this we need to scan + * forward until the last set bit before the end of the + * window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) break; + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_montgomery(r, r, &(val[wvalue >> 1]), mont, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend+1; + wvalue = 0; + start = 0; + if (wstart < 0) break; + } + if (!BN_from_montgomery(rr, r, mont, ctx)) goto err; + ret = 1; +err: + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + for (i = 0; i < ts; i++) + BN_clear_free(&(val[i])); + return (ret); +} + +int +BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + BN_MONT_CTX *mont = NULL; + int b, bits, ret = 0; + int r_is_one; + BN_ULONG w, next_w; + BIGNUM *d, *r, *t; + BIGNUM *swap_tmp; +#define BN_MOD_MUL_WORD(r, w, m) \ + (BN_mul_word(r, (w)) && \ + (/* BN_ucmp(r, (m)) < 0 ? 1 : */ \ + (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1)))) + /* BN_MOD_MUL_WORD is only used with 'w' large, + * so the BN_ucmp test is probably more overhead + * than always using BN_mod (which uses BN_copy if + * a similar test returns true). + */ + /* We can use BN_mod and do not need BN_nnmod because our + * accumulator is never negative (the result of BN_mod does + * not depend on the sign of the modulus). + */ +#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ + (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) + + bn_check_top(p); + bn_check_top(m); + + if (m->top == 0 || !(m->d[0] & 1)) { + BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS); + return (0); + } + if (m->top == 1) + a %= m->d[0]; /* make sure that 'a' is reduced */ + + bits = BN_num_bits(p); + if (bits == 0) { + ret = BN_one(rr); + return ret; + } + if (a == 0) { + ret = BN_zero(rr); + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + if (d == NULL || r == NULL || t == NULL) goto err; + + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) goto err; + } + + r_is_one = 1; /* except for Montgomery factor */ + + /* bits-1 >= 0 */ + + /* The result is accumulated in the product r*w. */ + w = a; /* bit 'bits-1' of 'p' is always set */ + for (b = bits-2; b >= 0; b--) { + /* First, square r*w. */ + next_w = w*w; + if ((next_w/w) != w) /* overflow */ { + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + next_w = 1; + } + w = next_w; + if (!r_is_one) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) goto err; + } + + /* Second, multiply r*w by 'a' if exponent bit is set. */ + if (BN_is_bit_set(p, b)) { + next_w = w*a; + if ((next_w/a) != w) /* overflow */ { + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + next_w = a; + } + w = next_w; + } + } + + /* Finally, set r: = r*w. */ + if (w != 1) { + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + } + + if (r_is_one) /* can happen only if a == 1 */ { + if (!BN_one(rr)) goto err; + } else { + if (!BN_from_montgomery(rr, r, mont, ctx)) goto err; + } + ret = 1; +err: + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + return (ret); +} + + +#ifdef NOT_NEEDED_FOR_DH +/* The old fallback, simple version :-) */ +int +BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue, ts = 0; + int start = 1; + BIGNUM *d; + BIGNUM val[TABLE_SIZE]; + + bits = BN_num_bits(p); + + if (bits == 0) { + ret = BN_one(r); + return ret; + } + + BN_CTX_start(ctx); + if ((d = BN_CTX_get(ctx)) == NULL) goto err; + + BN_init(&(val[0])); + ts = 1; + if (!BN_nnmod(&(val[0]), a, m, ctx)) goto err; /* 1 */ + if (BN_is_zero(&(val[0]))) { + ret = BN_zero(r); + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul(d, &(val[0]), &(val[0]), m, ctx)) + goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + BN_init(&(val[i])); + if (!BN_mod_mul(&(val[i]), &(val[i - 1]), d, m, ctx)) + goto err; + } + ts = i; + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. + */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits-1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + if (wstart == 0) break; + wstart--; + continue; + } + /* We now have wstart on a 'set' bit, we now need to work out + * how bit a window to do. To do this we need to scan + * forward until the last set bit before the end of the + * window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) break; + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend+1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul(r, r, &(val[wvalue >> 1]), m, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend+1; + wvalue = 0; + start = 0; + if (wstart < 0) break; + } + ret = 1; +err: + BN_CTX_end(ctx); + for (i = 0; i < ts; i++) + BN_clear_free(&(val[i])); + return (ret); +} + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); + +int +BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) +{ + BIGNUM *a, *b, *t; + int ret = 0; + + bn_check_top(in_a); + bn_check_top(in_b); + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (a == NULL || b == NULL) goto err; + + if (BN_copy(a, in_a) == NULL) goto err; + if (BN_copy(b, in_b) == NULL) goto err; + a->neg = 0; + b->neg = 0; + + if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } + t = euclid(a, b); + if (t == NULL) goto err; + + if (BN_copy(r, t) == NULL) goto err; + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +static BIGNUM * +euclid(BIGNUM *a, BIGNUM *b) +{ + BIGNUM *t; + int shifts = 0; + + bn_check_top(a); + bn_check_top(b); + + /* 0 <= b <= a */ + while (!BN_is_zero(b)) { + /* 0 < b <= a */ + + if (BN_is_odd(a)) { + if (BN_is_odd(b)) { + if (!BN_sub(a, a, b)) goto err; + if (!BN_rshift1(a, a)) goto err; + if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } + } else /* a odd - b even */ { + if (!BN_rshift1(b, b)) goto err; + if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } + } + } else /* a is even */ { + if (BN_is_odd(b)) { + if (!BN_rshift1(a, a)) goto err; + if (BN_cmp(a, b) < 0) { t = a; a = b; b = t; } + } else /* a even - b even */ { + if (!BN_rshift1(a, a)) goto err; + if (!BN_rshift1(b, b)) goto err; + shifts++; + } + } + /* 0 <= b <= a */ + } + + if (shifts) { + if (!BN_lshift(a, a, shifts)) goto err; + } + return (a); +err: + return (NULL); +} +#endif /* NOT_NEEDED_FOR_DH */ + + +/* solves ax == 1 (mod n) */ +BIGNUM * +BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + if (R == NULL) goto err; + + BN_one(X); + BN_zero(Y); + if (BN_copy(B, a) == NULL) goto err; + if (BN_copy(A, n) == NULL) goto err; + A->neg = 0; + if (B->neg || (BN_ucmp(B, A) >= 0)) { + if (!BN_nnmod(B, B, A, ctx)) goto err; + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { + /* Binary inversion algorithm; requires odd modulus. + * This is faster than the general algorithm if the modulus + * is sufficiently small (about 400 .. 500 bits on 32-bit + * sytems, but much more on 64-bit systems) + */ + int shift; + + while (!BN_is_zero(B)) { + /* + * 0 < B < |n|, + * 0 < A <= |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|) + */ + + /* Now divide B by the maximum possible power of two in the integers, + * and divide X by the same value mod |n|. + * When we're done, (1) still holds. + */ + shift = 0; + while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { + shift++; + + if (BN_is_odd(X)) { + if (!BN_uadd(X, X, n)) goto err; + } + /* now X is even, so we can easily divide it by two */ + if (!BN_rshift1(X, X)) goto err; + } + if (shift > 0) { + if (!BN_rshift(B, B, shift)) goto err; + } + + + /* Same for A and Y. Afterwards, (2) still holds. */ + shift = 0; + while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { + shift++; + + if (BN_is_odd(Y)) { + if (!BN_uadd(Y, Y, n)) goto err; + } + /* now Y is even */ + if (!BN_rshift1(Y, Y)) goto err; + } + if (shift > 0) { + if (!BN_rshift(A, A, shift)) goto err; + } + + /* We still have (1) and (2). + * Both A and B are odd. + * The following computations ensure that + * + * 0 <= B < |n|, + * 0 < A < |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|), + * + * and that either A or B is even in the next iteration. + */ + if (BN_ucmp(B, A) >= 0) { + /* -sign*(X + Y)*a == B - A (mod |n|) */ + if (!BN_uadd(X, X, Y)) goto err; + /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that + * actually makes the algorithm slower + */ + if (!BN_usub(B, B, A)) goto err; + } else { + /* sign*(X + Y)*a == A - B (mod |n|) */ + if (!BN_uadd(Y, Y, X)) goto err; + /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ + if (!BN_usub(A, A, B)) goto err; + } + } + } else { + /* general inversion algorithm */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* (D, M) : = (A/B, A%B) ... */ + if (BN_num_bits(A) == BN_num_bits(B)) { + if (!BN_one(D)) goto err; + if (!BN_sub(M, A, B)) goto err; + } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { + /* A/B is 1, 2, or 3 */ + if (!BN_lshift1(T, B)) goto err; + if (BN_ucmp(A, T) < 0) { + /* A < 2*B, so D = 1 */ + if (!BN_one(D)) goto err; + if (!BN_sub(M, A, B)) goto err; + } else { + /* A >= 2*B, so D = 2 or D = 3 */ + if (!BN_sub(M, A, T)) goto err; + if (!BN_add(D, T, B)) goto err; + /* use D ( := 3 * B) as temp */ + if (BN_ucmp(A, D) < 0) { + /* A < 3*B, so D = 2 */ + if (!BN_set_word(D, 2)) goto err; + /* M ( = A - 2*B) already has the correct value */ + } else { + /* only D = 3 remains */ + if (!BN_set_word(D, 3)) goto err; + /* currently M = A - 2 * B, + * but we need M = A - 3 * B + */ + if (!BN_sub(M, M, B)) goto err; + } + } + } else { + if (!BN_div(D, M, A, B, ctx)) goto err; + } + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) : = (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) : = (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + /* most of the time D is very small, so we can optimize tmp : = D*X+Y */ + if (BN_is_one(D)) { + if (!BN_add(tmp, X, Y)) goto err; + } else { + if (BN_is_word(D, 2)) { + if (!BN_lshift1(tmp, X)) goto err; + } else if (BN_is_word(D, 4)) { + if (!BN_lshift(tmp, X, 2)) goto err; + } else if (D->top == 1) { + if (!BN_copy(tmp, X)) goto err; + if (!BN_mul_word(tmp, D->d[0])) goto err; + } else { + if (!BN_mul(tmp, D, X, ctx)) goto err; + } + if (!BN_add(tmp, tmp, Y)) goto err; + } + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a, n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) goto err; + } + /* Now Y*a == A (mod |n|). */ + + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) goto err; + } + } else { + BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE); + goto err; + } + ret = R; +err: + if ((ret == NULL) && (in == NULL)) BN_free(R); + BN_CTX_end(ctx); + return (ret); +} + +#include + +#ifdef NOT_NEEDED_FOR_DH +/* For a 32 bit machine + * 2 - 4 == 128 + * 3 - 8 == 256 + * 4 - 16 == 512 + * 5 - 32 == 1024 + * 6 - 64 == 2048 + * 7 - 128 == 4096 + * 8 - 256 == 8192 + */ +static int bn_limit_bits = 0; +static int bn_limit_num = 8; /* (1 << bn_limit_bits) */ +static int bn_limit_bits_low = 0; +static int bn_limit_num_low = 8; /* (1 << bn_limit_bits_low) */ +static int bn_limit_bits_high = 0; +static int bn_limit_num_high = 8; /* (1 << bn_limit_bits_high) */ +static int bn_limit_bits_mont = 0; +static int bn_limit_num_mont = 8; /* (1 << bn_limit_bits_mont) */ + +void +BN_set_params(int mult, int high, int low, int mont) +{ + if (mult >= 0) { + if (mult > (sizeof(int)*8)-1) + mult = sizeof(int)*8-1; + bn_limit_bits = mult; + bn_limit_num = 1 << mult; + } + if (high >= 0) { + if (high > (sizeof(int)*8)-1) + high = sizeof(int)*8-1; + bn_limit_bits_high = high; + bn_limit_num_high = 1 << high; + } + if (low >= 0) { + if (low > (sizeof(int)*8)-1) + low = sizeof(int)*8-1; + bn_limit_bits_low = low; + bn_limit_num_low = 1 << low; + } + if (mont >= 0) { + if (mont > (sizeof(int)*8)-1) + mont = sizeof(int)*8-1; + bn_limit_bits_mont = mont; + bn_limit_num_mont = 1 << mont; + } +} + +int +BN_get_params(int which) +{ + if (which == 0) return (bn_limit_bits); + else if (which == 1) return (bn_limit_bits_high); + else if (which == 2) return (bn_limit_bits_low); + else if (which == 3) return (bn_limit_bits_mont); + else return (0); +} + +char * +BN_options(void) +{ + static int init = 0; + static char data[16]; + + if (!init) { + init++; +#ifdef BN_LLONG + sprintf(data, "bn(%d, %d)", (int)sizeof(BN_ULLONG)*8, + (int)sizeof(BN_ULONG)*8); +#else + sprintf(data, "bn(%d, %d)", (int)sizeof(BN_ULONG)*8, + (int)sizeof(BN_ULONG)*8); +#endif + } + return (data); +} +#endif /* NOT_NEEDED_FOR_DH */ + +const BIGNUM * +BN_value_one(void) +{ + static BN_ULONG data_one = 1L; + static BIGNUM const_one = {&data_one, 1, 1, 0}; + + return (&const_one); +} + +int +BN_num_bits_word(BN_ULONG l) +{ + static const char bits[256] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 + }; + +#if defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffffffff00000000L) { + if (l & 0xffff000000000000L) { + if (l & 0xff00000000000000L) { + return (bits[(int)(l >> 56)] + 56); + } else + return (bits[(int)(l >> 48)] + 48); + } else { + if (l & 0x0000ff0000000000L) { + return (bits[(int)(l >> 40)] + 40); + } else + return (bits[(int)(l >> 32)] + 32); + } + } else +#else +#ifdef SIXTY_FOUR_BIT + if (l & 0xffffffff00000000LL) { + if (l & 0xffff000000000000LL) { + if (l & 0xff00000000000000LL) { + return (bits[(int)(l >> 56)] + 56); + } else + return (bits[(int)(l >> 48)] + 48); + } else { + if (l & 0x0000ff0000000000LL) { + return (bits[(int)(l >> 40)] + 40); + } else + return (bits[(int)(l >> 32)] + 32); + } + } else +#endif +#endif /* SIXTY_FOUR_BIT_LONG */ + { +#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffff0000L) { + if (l & 0xff000000L) + return (bits[(int)(l >> 24L)] + 24); + else + return (bits[(int)(l >> 16L)] + 16); + } else +#endif + { +#if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || \ + defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xff00L) + return (bits[(int)(l >> 8)] + 8); + else +#endif + return (bits[(int)(l)]); + } + } +} + +int +BN_num_bits(const BIGNUM *a) +{ + BN_ULONG l; + int i; + + bn_check_top(a); + + if (a->top == 0) return (0); + l = a->d[a->top-1]; + assert(l != 0); + i = (a->top-1)*BN_BITS2; + return (i+BN_num_bits_word(l)); +} + +void +BN_clear_free(BIGNUM *a) +{ + int i; + + if (a == NULL) return; + if (a->d != NULL) { + OPENSSL_cleanse(a->d, a->dmax*sizeof(a->d[0])); + if (!(BN_get_flags(a, BN_FLG_STATIC_DATA))) + OPENSSL_free(a->d); + } + i = BN_get_flags(a, BN_FLG_MALLOCED); + OPENSSL_cleanse(a, sizeof(BIGNUM)); + if (i) + OPENSSL_free(a); +} + +void +BN_free(BIGNUM *a) +{ + if (a == NULL) return; + if ((a->d != NULL) && !(BN_get_flags(a, BN_FLG_STATIC_DATA))) + OPENSSL_free(a->d); + a->flags |= BN_FLG_FREE; /* REMOVE? */ + if (a->flags & BN_FLG_MALLOCED) + OPENSSL_free(a); +} + +void +BN_init(BIGNUM *a) +{ + memset(a, 0, sizeof(BIGNUM)); +} + +BIGNUM * +BN_new(void) +{ + BIGNUM *ret; + + if ((ret = (BIGNUM *)OPENSSL_malloc(sizeof(BIGNUM))) == NULL) { + BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->flags = BN_FLG_MALLOCED; + ret->top = 0; + ret->neg = 0; + ret->dmax = 0; + ret->d = NULL; + return (ret); +} + +/* This is used both by bn_expand2() and bn_dup_expand() */ +/* The caller MUST check that words > b->dmax before calling this */ +static BN_ULONG * +bn_expand_internal(const BIGNUM *b, int words) +{ + BN_ULONG *A, *a = NULL; + const BN_ULONG *B; + int i; + + if (words > (INT_MAX/(4*BN_BITS2))) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + + bn_check_top(b); + if (BN_get_flags(b, BN_FLG_STATIC_DATA)) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return (NULL); + } + a = A = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG)*(words+1)); + if (A == NULL) { + BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE); + return (NULL); + } + B = b->d; + /* Check if the previous number needs to be copied */ + if (B != NULL) { + for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) { + /* + * The fact that the loop is unrolled + * 4-wise is a tribute to Intel. It's + * the one that doesn't have enough + * registers to accomodate more data. + * I'd unroll it 8-wise otherwise:-) + * + * + */ + BN_ULONG a0, a1, a2, a3; + a0 = B[0]; a1 = B[1]; a2 = B[2]; a3 = B[3]; + A[0] = a0; A[1] = a1; A[2] = a2; A[3] = a3; + } + switch (b->top&3) { + case 3: A[2] = B[2]; + case 2: A[1] = B[1]; + case 1: A[0] = B[0]; + case 0: + ; + } + } + + /* Now need to zero any data between b->top and b->max */ + + A = &(a[b->top]); + for (i = (words - b->top) >> 3; i > 0; i--, A += 8) { + A[0] = 0; A[1] = 0; A[2] = 0; A[3] = 0; + A[4] = 0; A[5] = 0; A[6] = 0; A[7] = 0; + } + for (i = (words - b->top) & 7; i > 0; i--, A++) + A[0] = 0; + + return (a); +} + +#ifdef NOT_NEEDED_FOR_DH +/* This is an internal function that can be used instead of bn_expand2() + * when there is a need to copy BIGNUMs instead of only expanding the + * data part, while still expanding them. + * Especially useful when needing to expand BIGNUMs that are declared + * 'const' and should therefore not be changed. + * The reason to use this instead of a BN_dup() followed by a bn_expand2() + * is memory allocation overhead. A BN_dup() followed by a bn_expand2() + * will allocate new memory for the BIGNUM data twice, and free it once, + * while bn_dup_expand() makes sure allocation is made only once. + */ + +BIGNUM * +bn_dup_expand(const BIGNUM *b, int words) +{ + BIGNUM *r = NULL; + + /* This function does not work if + * words <= b->dmax && top < words + * because BN_dup() does not preserve 'dmax'! + * (But bn_dup_expand() is not used anywhere yet.) + */ + + if (words > b->dmax) { + BN_ULONG *a = bn_expand_internal(b, words); + + if (a) { + r = BN_new(); + if (r) { + r->top = b->top; + r->dmax = words; + r->neg = b->neg; + r->d = a; + } else { + /* r == NULL, BN_new failure */ + OPENSSL_free(a); + } + } + /* If a == NULL, there was an error in allocation in + * bn_expand_internal(), and NULL should be returned + */ + } else { + r = BN_dup(b); + } + + return r; +} +#endif /* NOT_NEEDED_FOR_DH */ + +/* This is an internal function that should not be used in applications. + * It ensures that 'b' has enough room for a 'words' word number number. + * It is mostly used by the various BIGNUM routines. If there is an error, + * NULL is returned. If not, 'b' is returned. + */ + +BIGNUM * +bn_expand2(BIGNUM *b, int words) +{ + if (words > b->dmax) { + BN_ULONG *a = bn_expand_internal(b, words); + + if (a) { + if (b->d) + OPENSSL_free(b->d); + b->d = a; + b->dmax = words; + } else + b = NULL; + } + return b; +} + +#ifdef BCMDH_TEST +BIGNUM * +BN_dup(const BIGNUM *a) +{ + BIGNUM *r, *t; + + if (a == NULL) return NULL; + + bn_check_top(a); + + t = BN_new(); + if (t == NULL) return (NULL); + r = BN_copy(t, a); + /* now r == t || r == NULL */ + if (r == NULL) + BN_free(t); + return r; +} +#endif /* BCMDH_TEST */ + +BIGNUM * +BN_copy(BIGNUM *a, const BIGNUM *b) +{ + int i; + BN_ULONG *A; + const BN_ULONG *B; + + bn_check_top(b); + + if (a == b) return (a); + if (bn_wexpand(a, b->top) == NULL) return (NULL); + + A = a->d; + B = b->d; + for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) { + BN_ULONG a0, a1, a2, a3; + a0 = B[0]; a1 = B[1]; a2 = B[2]; a3 = B[3]; + A[0] = a0; A[1] = a1; A[2] = a2; A[3] = a3; + } + switch (b->top & 3) { + case 3: A[2] = B[2]; + case 2: A[1] = B[1]; + case 1: A[0] = B[0]; + case 0: ; + } + +/* memset(&(a->d[b->top]), 0, sizeof(a->d[0])*(a->max-b->top)); */ + a->top = b->top; + if ((a->top == 0) && (a->d != NULL)) + a->d[0] = 0; + a->neg = b->neg; + return (a); +} + +#ifdef NOT_NEEDED_FOR_DH +void +BN_swap(BIGNUM *a, BIGNUM *b) +{ + int flags_old_a, flags_old_b; + BN_ULONG *tmp_d; + int tmp_top, tmp_dmax, tmp_neg; + + flags_old_a = a->flags; + flags_old_b = b->flags; + + tmp_d = a->d; + tmp_top = a->top; + tmp_dmax = a->dmax; + tmp_neg = a->neg; + + a->d = b->d; + a->top = b->top; + a->dmax = b->dmax; + a->neg = b->neg; + + b->d = tmp_d; + b->top = tmp_top; + b->dmax = tmp_dmax; + b->neg = tmp_neg; + + a->flags = (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA); + b->flags = (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA); +} + + +void +BN_clear(BIGNUM *a) +{ + if (a->d != NULL) + memset(a->d, 0, a->dmax*sizeof(a->d[0])); + a->top = 0; + a->neg = 0; +} + +BN_ULONG +BN_get_word(const BIGNUM *a) +{ + int i, n; + BN_ULONG ret = 0; + + n = BN_num_bytes(a); + if (n > sizeof(BN_ULONG)) + return (BN_MASK2); + for (i = a->top-1; i >= 0; i--) { +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + ret <<= BN_BITS4; /* stops the compiler complaining */ + ret <<= BN_BITS4; +#else + ret = 0; +#endif + ret |= a->d[i]; + } + return (ret); +} +#endif /* NOT_NEEDED_FOR_DH */ + +int +BN_set_word(BIGNUM *a, BN_ULONG w) +{ + int i, n; + if (bn_expand(a, (int)sizeof(BN_ULONG)*8) == NULL) return (0); + + n = sizeof(BN_ULONG)/BN_BYTES; + a->neg = 0; + a->top = 0; + a->d[0] = (BN_ULONG)w&BN_MASK2; + if (a->d[0] != 0) a->top = 1; + for (i = 1; i < n; i++) { + /* the following is done instead of + * w >>= BN_BITS2 so compilers don't complain + * on builds where sizeof(long) == BN_TYPES + */ +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + w >>= BN_BITS4; + w >>= BN_BITS4; +#else + w = 0; +#endif + a->d[i] = (BN_ULONG)w&BN_MASK2; + if (a->d[i] != 0) a->top = i+1; + } + return (1); +} + +BIGNUM * +BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + + if (ret == NULL) ret = BN_new(); + if (ret == NULL) return (NULL); + l = 0; + n = len; + if (n == 0) { + ret->top = 0; + return (ret); + } + if (bn_expand(ret, (int)(n+2)*8) == NULL) + return (NULL); + i = ((n-1)/BN_BYTES)+1; + m = ((n-1)%(BN_BYTES)); + ret->top = i; + ret->neg = 0; + while (n-- > 0) { + l = (l << 8L)| *(s++); + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES-1; + } + } + /* need to call this due to clear byte at top if avoiding + * having the top bit set (-ve number) + */ + bn_fix_top(ret); + return (ret); +} + +/* ignore negative */ +int +BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + int n, i; + BN_ULONG l; + + n = i = BN_num_bytes(a); + while (i-- > 0) { + l = a->d[i/BN_BYTES]; + *(to++) = (unsigned char)(l>>(8*(i%BN_BYTES)))&0xff; + } + return (n); +} + +int +BN_ucmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + BN_ULONG t1, t2, *ap, *bp; + + bn_check_top(a); + bn_check_top(b); + + i = a->top-b->top; + if (i != 0) return (i); + ap = a->d; + bp = b->d; + for (i = a->top-1; i >= 0; i--) { + t1 = ap[i]; + t2 = bp[i]; + if (t1 != t2) + return (t1 > t2?1:-1); + } + return (0); +} + +#ifdef BCMDH_TEST +int +BN_cmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + int gt, lt; + BN_ULONG t1, t2; + + if ((a == NULL) || (b == NULL)) { + if (a != NULL) + return (-1); + else if (b != NULL) + return (1); + else + return (0); + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) { + if (a->neg) + return (-1); + else return (1); + } + if (a->neg == 0) { + gt = 1; lt = -1; + } else { + gt = -1; lt = 1; + } + + if (a->top > b->top) return (gt); + if (a->top < b->top) return (lt); + for (i = a->top-1; i >= 0; i--) { + t1 = a->d[i]; + t2 = b->d[i]; + if (t1 > t2) return (gt); + if (t1 < t2) return (lt); + } + return (0); +} +#endif /* BCMDH_TEST */ + +int +BN_set_bit(BIGNUM *a, int n) +{ + int i, j, k; + + i = n/BN_BITS2; + j = n%BN_BITS2; + if (a->top <= i) { + if (bn_wexpand(a, i + 1) == NULL) return (0); + for (k = a->top; k < i + 1; k++) + a->d[k] = 0; + a->top = i+1; + } + + a->d[i] |= (((BN_ULONG)1) << j); + return (1); +} + +#ifdef NOT_NEEDED_FOR_DH +int +BN_clear_bit(BIGNUM *a, int n) +{ + int i, j; + + i = n/BN_BITS2; + j = n%BN_BITS2; + if (a->top <= i) return (0); + + a->d[i] &= (~(((BN_ULONG)1) << j)); + bn_fix_top(a); + return (1); +} +#endif /* NOT_NEEDED_FOR_DH */ + +int +BN_is_bit_set(const BIGNUM *a, int n) +{ + int i, j; + + if (n < 0) return (0); + i = n/BN_BITS2; + j = n%BN_BITS2; + if (a->top <= i) return (0); + return ((a->d[i]&(((BN_ULONG)1) << j)) ? 1 : 0); +} + +#ifdef NOT_NEEDED_FOR_DH +int +BN_mask_bits(BIGNUM *a, int n) +{ + int b, w; + + w = n/BN_BITS2; + b = n%BN_BITS2; + if (w >= a->top) return (0); + if (b == 0) + a->top = w; + else { + a->top = w+1; + a->d[w] &= ~(BN_MASK2 << b); + } + bn_fix_top(a); + return (1); +} +#endif /* NOT_NEEDED_FOR_DH */ + +int +bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) +{ + int i; + BN_ULONG aa, bb; + + aa = a[n-1]; + bb = b[n-1]; + if (aa != bb) return ((aa > bb)?1:-1); + for (i = n-2; i >= 0; i--) { + aa = a[i]; + bb = b[i]; + if (aa != bb) return ((aa > bb)?1:-1); + } + return (0); +} + +#ifdef NOT_NEEDED_FOR_DH +/* Here follows a specialised variants of bn_cmp_words(). It has the + * property of performing the operation on arrays of different sizes. + * The sizes of those arrays is expressed through cl, which is the + * common length ( basicall, min(len(a), len(b)) ), and dl, which is the + * delta between the two lengths, calculated as len(a)-len(b). + * All lengths are the number of BN_ULONGs... + */ + +int +bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) +{ + int n, i; + n = cl-1; + + if (dl < 0) { + for (i = dl; i < 0; i++) { + if (b[n - i] != 0) + return -1; /* a < b */ + } + } + if (dl > 0) { + for (i = dl; i > 0; i--) { + if (a[n + i] != 0) + return 1; /* a > b */ + } + } + return bn_cmp_words(a, b, cl); +} +#endif /* NOT_NEEDED_FOR_DH */ + + + +int +BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) +{ + /* like BN_mod, but returns non-negative remainder + * (i.e., 0 <= r < |d| always holds) + */ + + if (!(BN_mod(r, m, d, ctx))) + return 0; + if (!r->neg) + return 1; + /* now -|d| < r < 0, so we have to set r : = r + |d| */ + return (d->neg ? BN_sub : BN_add)(r, r, d); +} + + +#ifdef NOT_NEEDED_FOR_DH +int +BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_add(r, a, b)) + return 0; + return BN_nnmod(r, r, m, ctx); +} + + +/* BN_mod_add variant that may be used if both a and b are non-negative + * and less than m + */ +int +BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) +{ + if (!BN_add(r, a, b)) return 0; + if (BN_ucmp(r, m) >= 0) + return BN_usub(r, r, m); + return 1; +} + +int +BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_sub(r, a, b)) return 0; + return BN_nnmod(r, r, m, ctx); +} + +/* BN_mod_sub variant that may be used if both a and b are non-negative + * and less than m + */ +int +BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) +{ + if (!BN_sub(r, a, b)) + return 0; + if (r->neg) + return BN_add(r, r, m); + return 1; +} +#endif /* NOT_NEEDED_FOR_DH */ + +#ifdef BCMDH_TEST +/* slow but works */ +int +BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) +{ + BIGNUM *t; + int ret = 0; + + bn_check_top(a); + bn_check_top(b); + bn_check_top(m); + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) == NULL) goto err; + if (a == b) { if (!BN_sqr(t, a, ctx)) goto err; } + else { if (!BN_mul(t, a, b, ctx)) goto err; } + if (!BN_nnmod(r, t, m, ctx)) goto err; + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} +#endif /* BCMDH_TEST */ + + +#ifdef NOT_NEEDED_FOR_DH +int +BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_sqr(r, a, ctx)) return 0; + /* r->neg == 0, thus we don't need BN_nnmod */ + return BN_mod(r, r, m, ctx); +} + + +int +BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_lshift1(r, a)) + return 0; + return BN_nnmod(r, r, m, ctx); +} + + +/* BN_mod_lshift1 variant that may be used if a is non-negative + * and less than m + */ +int +BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) +{ + if (!BN_lshift1(r, a)) return 0; + if (BN_cmp(r, m) >= 0) + return BN_sub(r, r, m); + return 1; +} + + +int +BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx) +{ + BIGNUM *abs_m = NULL; + int ret; + + if (!BN_nnmod(r, a, m, ctx)) + return 0; + + if (m->neg) { + abs_m = BN_dup(m); + if (abs_m == NULL) return 0; + abs_m->neg = 0; + } + + ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + + if (abs_m) + BN_free(abs_m); + return ret; +} + + +/* BN_mod_lshift variant that may be used if a is non-negative + * and less than m + */ +int +BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) +{ + if (r != a) { + if (BN_copy(r, a) == NULL) return 0; + } + + while (n > 0) { + int max_shift; + + /* 0 < r < m */ + max_shift = BN_num_bits(m) - BN_num_bits(r); + /* max_shift >= 0 */ + + if (max_shift < 0) { + BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED); + return 0; + } + + if (max_shift > n) + max_shift = n; + + if (max_shift) { + if (!BN_lshift(r, r, max_shift)) return 0; + n -= max_shift; + } else { + if (!BN_lshift1(r, r)) return 0; + --n; + } + + /* BN_num_bits(r) <= BN_num_bits(m) */ + + if (BN_cmp(r, m) >= 0) { + if (!BN_sub(r, r, m)) return 0; + } + } + + return 1; +} +#endif /* NOT_NEEDED_FOR_DH */ + +/* + * Details about Montgomery multiplication algorithms can be found at + * http://security.ece.orst.edu/publications.html, e.g. + * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and + * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf + */ + + +#define MONT_WORD /* use the faster word-based algorithm */ + +int +BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) +{ + BIGNUM *tmp; + int ret = 0; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) goto err; + + bn_check_top(tmp); + if (a == b) { + if (!BN_sqr(tmp, a, ctx)) goto err; + } else { + if (!BN_mul(tmp, a, b, ctx)) goto err; + } + /* reduce from aRR to aR */ + if (!BN_from_montgomery(r, tmp, mont, ctx)) goto err; + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +int +BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) +{ + int retn = 0; + +#ifdef MONT_WORD + BIGNUM *n, *r; + BN_ULONG *ap, *np, *rp, n0, v, *nrp; + int al, nl, max, i, x, ri; + + BN_CTX_start(ctx); + if ((r = BN_CTX_get(ctx)) == NULL) goto err; + + if (!BN_copy(r, a)) goto err; + n = &(mont->N); + + ap = a->d; + /* mont->ri is the size of mont->N in bits (rounded up + * to the word size) + */ + al = ri = mont->ri/BN_BITS2; + + nl = n->top; + if ((al == 0) || (nl == 0)) { + r->top = 0; + return (1); + } + + max = (nl + al + 1); + if (bn_wexpand(r, max) == NULL) + goto err; + if (bn_wexpand(ret, max) == NULL) + goto err; + + r->neg = a->neg^n->neg; + np = n->d; + rp = r->d; + nrp = &(r->d[nl]); + + /* clear the top words of T */ + for (i = r->top; i < max; i++) + r->d[i] = 0; + + r->top = max; + n0 = mont->n0; + +#ifdef BN_COUNT + fprintf(stderr, "word BN_from_montgomery %d * %d\n", nl, nl); +#endif + for (i = 0; i < nl; i++) { +#ifdef __TANDEM + { + long long t1; + long long t2; + long long t3; + t1 = rp[0] * (n0 & 0177777); + t2 = 037777600000l; + t2 = n0 & t2; + t3 = rp[0] & 0177777; + t2 = (t3 * t2) & BN_MASK2; + t1 = t1 + t2; + v = bn_mul_add_words(rp, np, nl, (BN_ULONG) t1); + } +#else + v = bn_mul_add_words(rp, np, nl, (rp[0]*n0)&BN_MASK2); +#endif + nrp++; + rp++; + if (((nrp[-1] += v)&BN_MASK2) >= v) + continue; + else { + if (((++nrp[0])&BN_MASK2) != 0) continue; + if (((++nrp[1])&BN_MASK2) != 0) continue; + for (x = 2; (((++nrp[x]) & BN_MASK2) == 0); x++) + ; + } + } + bn_fix_top(r); + + /* mont->ri will be a multiple of the word size */ + ret->neg = r->neg; + x = ri; + rp = ret->d; + ap = &(r->d[x]); + if (r->top < x) + al = 0; + else + al = r->top-x; + ret->top = al; + al -= 4; + for (i = 0; i < al; i += 4) { + BN_ULONG t1, t2, t3, t4; + + t1 = ap[i+0]; + t2 = ap[i+1]; + t3 = ap[i+2]; + t4 = ap[i+3]; + rp[i+0] = t1; + rp[i+1] = t2; + rp[i+2] = t3; + rp[i+3] = t4; + } + al += 4; + for (; i < al; i++) + rp[i] = ap[i]; +#else /* !MONT_WORD */ + BIGNUM *t1, *t2; + + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) goto err; + + if (!BN_copy(t1, a)) goto err; + BN_mask_bits(t1, mont->ri); + + if (!BN_mul(t2, t1, &mont->Ni, ctx)) goto err; + BN_mask_bits(t2, mont->ri); + + if (!BN_mul(t1, t2, &mont->N, ctx)) goto err; + if (!BN_add(t2, a, t1)) goto err; + if (!BN_rshift(ret, t2, mont->ri)) goto err; +#endif /* MONT_WORD */ + + if (BN_ucmp(ret, &(mont->N)) >= 0) { + if (!BN_usub(ret, ret, &(mont->N))) goto err; + } + retn = 1; +err: + BN_CTX_end(ctx); + return (retn); +} + +BN_MONT_CTX * +BN_MONT_CTX_new(void) +{ + BN_MONT_CTX *ret; + + if ((ret = (BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL) + return (NULL); + + BN_MONT_CTX_init(ret); + ret->flags = BN_FLG_MALLOCED; + return (ret); +} + +void +BN_MONT_CTX_init(BN_MONT_CTX *ctx) +{ + ctx->ri = 0; + BN_init(&(ctx->RR)); + BN_init(&(ctx->N)); + BN_init(&(ctx->Ni)); + ctx->flags = 0; +} + +void +BN_MONT_CTX_free(BN_MONT_CTX *mont) +{ + if (mont == NULL) + return; + + BN_free(&(mont->RR)); + BN_free(&(mont->N)); + BN_free(&(mont->Ni)); + if (mont->flags & BN_FLG_MALLOCED) + OPENSSL_free(mont); +} + +int +BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) +{ + BIGNUM Ri, *R; + + BN_init(&Ri); + R = &(mont->RR); /* grab RR as a temp */ + BN_copy(&(mont->N), mod); /* Set N */ + mont->N.neg = 0; + +#ifdef MONT_WORD + { + BIGNUM tmod; + BN_ULONG buf[2]; + + mont->ri = (BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; + if (!(BN_zero(R))) goto err; + if (!(BN_set_bit(R, BN_BITS2))) goto err; /* R */ + + buf[0] = mod->d[0]; /* tmod = N mod word size */ + buf[1] = 0; + tmod.d = buf; + tmod.top = 1; + tmod.dmax = 2; + tmod.neg = 0; + /* Ri = R^-1 mod N */ + if ((BN_mod_inverse(&Ri, R, &tmod, ctx)) == NULL) + goto err; + if (!BN_lshift(&Ri, &Ri, BN_BITS2)) goto err; /* R*Ri */ + if (!BN_is_zero(&Ri)) { + if (!BN_sub_word(&Ri, 1)) goto err; + } else { + /* if N mod word size == 1 */ + if (!BN_set_word(&Ri, BN_MASK2)) goto err; /* Ri-- (mod word size) */ + } + if (!BN_div(&Ri, NULL, &Ri, &tmod, ctx)) goto err; + /* Ni = (R*Ri-1)/N, + * keep only least significant word: + */ + mont->n0 = (Ri.top > 0) ? Ri.d[0] : 0; + BN_free(&Ri); + } +#else /* !MONT_WORD */ + { + /* bignum version */ + mont->ri = BN_num_bits(&mont->N); + if (!BN_zero(R)) goto err; + if (!BN_set_bit(R, mont->ri)) goto err; /* R = 2^ri */ + /* Ri = R^-1 mod N */ + if ((BN_mod_inverse(&Ri, R, &mont->N, ctx)) == NULL) + goto err; + if (!BN_lshift(&Ri, &Ri, mont->ri)) goto err; /* R*Ri */ + if (!BN_sub_word(&Ri, 1)) goto err; + /* Ni = (R*Ri-1) / N */ + if (!BN_div(&(mont->Ni), NULL, &Ri, &mont->N, ctx)) goto err; + BN_free(&Ri); + } +#endif /* MONT_WORD */ + + /* setup RR for conversions */ + if (!BN_zero(&(mont->RR))) goto err; + if (!BN_set_bit(&(mont->RR), mont->ri*2)) goto err; + if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) goto err; + + return (1); +err: + return (0); +} + +#ifdef NOT_NEEDED_FOR_DH +BN_MONT_CTX * +BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) +{ + if (to == from) return (to); + + if (!BN_copy(&(to->RR), &(from->RR))) return NULL; + if (!BN_copy(&(to->N), &(from->N))) return NULL; + if (!BN_copy(&(to->Ni), &(from->Ni))) return NULL; + to->ri = from->ri; + to->n0 = from->n0; + return (to); +} +#endif /* NOT_NEEDED_FOR_DH */ + + +#ifdef BN_RECURSION +/* Karatsuba recursive multiplication algorithm + * (cf. Knuth, The Art of Computer Programming, Vol. 2) + */ + +/* r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void +bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, BN_ULONG *t) +{ + int n = n2/2, c1, c2; + unsigned int neg, zero; + BN_ULONG ln, lo, *p; + +#ifdef BN_COUNT + printf(" bn_mul_recursive %d * %d\n", n2, n2); +#endif +#ifdef BN_MUL_COMBA + if (n2 == 8) { + bn_mul_comba8(r, a, b); + return; + } +#endif /* BN_MUL_COMBA */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { + /* This should not happen */ + bn_mul_normal(r, a, n2, b, n2); + return; + } + /* r = (a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + c2 = bn_cmp_words(&(b[n]), b, n); + zero = neg = 0; + switch (c1*3+c2) { + case -4: + bn_sub_words(t, &(a[n]), a, n); /* - */ + bn_sub_words(&(t[n]), b, &(b[n]), n); /* - */ + break; + case -3: + zero = 1; + break; + case -2: + bn_sub_words(t, &(a[n]), a, n); /* - */ + bn_sub_words(&(t[n]), &(b[n]), b, n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + break; + case 2: + bn_sub_words(t, a, &(a[n]), n); /* + */ + bn_sub_words(&(t[n]), b, &(b[n]), n); /* - */ + neg = 1; + break; + case 3: + zero = 1; + break; + case 4: + bn_sub_words(t, a, &(a[n]), n); + bn_sub_words(&(t[n]), &(b[n]), b, n); + break; + } + +# ifdef BN_MUL_COMBA + if (n == 4) { + if (!zero) + bn_mul_comba4(&(t[n2]), t, &(t[n])); + else + memset(&(t[n2]), 0, 8*sizeof(BN_ULONG)); + + bn_mul_comba4(r, a, b); + bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); + } else if (n == 8) { + if (!zero) + bn_mul_comba8(&(t[n2]), t, &(t[n])); + else + memset(&(t[n2]), 0, 16*sizeof(BN_ULONG)); + + bn_mul_comba8(r, a, b); + bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); + } else +# endif /* BN_MUL_COMBA */ + { + p = &(t[n2*2]); + if (!zero) + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, p); + else + memset(&(t[n2]), 0, n2*sizeof(BN_ULONG)); + bn_mul_recursive(r, a, b, n, p); + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, p); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { + /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n+n2]); + lo = *p; + ln = (lo+c1)&BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo+1)&BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/* n+tn is the word length + * t needs to be n*4 is size, as does r + */ +void +bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn, int n, BN_ULONG *t) +{ + int i, j, n2 = n*2; + int c1, c2, neg, zero; + BN_ULONG ln, lo, *p; + +# ifdef BN_COUNT + printf(" bn_mul_part_recursive %d * %d\n", tn+n, tn+n); +# endif + if (n < 8) { + i = tn+n; + bn_mul_normal(r, a, i, b, i); + return; + } + + /* r = (a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + c2 = bn_cmp_words(&(b[n]), b, n); + zero = neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_words(t, &(a[n]), a, n); /* - */ + bn_sub_words(&(t[n]), b, &(b[n]), n); /* - */ + break; + case -3: + zero = 1; + /* break; */ + case -2: + bn_sub_words(t, &(a[n]), a, n); /* - */ + bn_sub_words(&(t[n]), &(b[n]), b, n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + /* break; */ + case 2: + bn_sub_words(t, a, &(a[n]), n); /* + */ + bn_sub_words(&(t[n]), b, &(b[n]), n); /* - */ + neg = 1; + break; + case 3: + zero = 1; + /* break; */ + case 4: + bn_sub_words(t, a, &(a[n]), n); + bn_sub_words(&(t[n]), &(b[n]), b, n); + break; + } + /* The zero case isn't yet implemented here. The speedup + * would probably be negligible. + */ + if (n == 8) { + bn_mul_comba8(&(t[n2]), t, &(t[n])); + bn_mul_comba8(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); + memset(&(r[n2+tn*2]), 0, sizeof(BN_ULONG)*(n2-tn*2)); + } else { + p = &(t[n2*2]); + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, p); + bn_mul_recursive(r, a, b, n, p); + i = n/2; + /* If there is only a bottom half to the number, + * just do it + */ + j = tn-i; + if (j == 0) { + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, p); + memset(&(r[n2+i*2]), 0, sizeof(BN_ULONG)*(n2-i*2)); + } else if (j > 0) { + /* eg, n == 16, i == 8 and tn == 11 */ + bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), j, i, p); + memset(&(r[n2+tn*2]), 0, sizeof(BN_ULONG)*(n2-tn*2)); + } else { + /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + memset(&(r[n2]), 0, sizeof(BN_ULONG)*n2); + if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); + } else { + for (;;) { + i /= 2; + if (i < tn) { + bn_mul_part_recursive(&(r[n2]), + &(a[n]), &(b[n]), + tn-i, i, p); + break; + } else if (i == tn) { + bn_mul_recursive(&(r[n2]), + &(a[n]), &(b[n]), + i, p); + break; + } + } + } + } + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) /* if t[32] is negative */ { + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n+n2]); + lo = *p; + ln = (lo+c1)&BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo+1)&BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +#ifdef NOT_NEEDED_FOR_DH +/* a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + */ +void +bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, BN_ULONG *t) +{ + int n = n2/2; + +# ifdef BN_COUNT + printf(" bn_mul_low_recursive %d * %d\n", n2, n2); +# endif + + bn_mul_recursive(r, a, b, n, &(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) { + bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + } else { + bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n); + bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[n]), n); + } +} +#endif /* NOT_NEEDED_FOR_DH */ + +/* a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + * l is the low words of the output. + * t needs to be n2*3 + */ +void +bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2, BN_ULONG *t) +{ + int i, n; + int c1, c2; + int neg, oneg, zero; + BN_ULONG ll, lc, *lp, *mp; + +# ifdef BN_COUNT + printf(" bn_mul_high %d * %d\n", n2, n2); +# endif + n = n2 / 2; + + /* Calculate (al - ah) * (bh - bl) */ + neg = zero = 0; + c1 = bn_cmp_words(&(a[0]), &(a[n]), n); + c2 = bn_cmp_words(&(b[n]), &(b[0]), n); + switch (c1 * 3 + c2) { + case -4: + bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n); + bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n); + break; + case -3: + zero = 1; + break; + case -2: + bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n); + bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n); + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + break; + case 2: + bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n); + bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n); + neg = 1; + break; + case 3: + zero = 1; + break; + case 4: + bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n); + bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n); + break; + } + + oneg = neg; + /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */ + /* r[10] = (a[1]*b[1]) */ +# ifdef BN_MUL_COMBA + if (n == 8) { + bn_mul_comba8(&(t[0]), &(r[0]), &(r[n])); + bn_mul_comba8(r, &(a[n]), &(b[n])); + } else +# endif + { + bn_mul_recursive(&(t[0]), &(r[0]), &(r[n]), n, &(t[n2])); + bn_mul_recursive(r, &(a[n]), &(b[n]), n, &(t[n2])); + } + + /* s0 == low(al*bl) + * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl) + * We know s0 and s1 so the only unknown is high(al*bl) + * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl)) + * high(al*bl) == s1 - (r[0]+l[0]+t[0]) + */ + if (l != NULL) { + lp = &(t[n2+n]); + c1 = (int)(bn_add_words(lp, &(r[0]), &(l[0]), n)); + } else { + c1 = 0; + lp = &(r[0]); + } + + if (neg) + neg = (int)(bn_sub_words(&(t[n2]), lp, &(t[0]), n)); + else { + bn_add_words(&(t[n2]), lp, &(t[0]), n); + neg = 0; + } + + if (l != NULL) { + bn_sub_words(&(t[n2+n]), &(l[n]), &(t[n2]), n); + } else { + lp = &(t[n2+n]); + mp = &(t[n2]); + for (i = 0; i < n; i++) + lp[i] = ((~mp[i])+1)&BN_MASK2; + } + + /* s[0] = low(al*bl) + * t[3] = high(al*bl) + * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign + * r[10] = (a[1]*b[1]) + */ + /* R[10] = al*bl + * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0]) + * R[32] = ah*bh + */ + /* R[1] = t[3]+l[0]+r[0](+-)t[0] (have carry/borrow) + * R[2] = r[0]+t[3]+r[1](+-)t[1] (have carry/borrow) + * R[3] = r[1]+(carry/borrow) + */ + if (l != NULL) { + lp = &(t[n2]); + c1 = (int)(bn_add_words(lp, &(t[n2+n]), &(l[0]), n)); + } else { + lp = &(t[n2+n]); + c1 = 0; + } + c1 += (int)(bn_add_words(&(t[n2]), lp, &(r[0]), n)); + if (oneg) + c1 -= (int)(bn_sub_words(&(t[n2]), &(t[n2]), &(t[0]), n)); + else + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), &(t[0]), n)); + + c2 = (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n2+n]), n)); + c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(r[n]), n)); + if (oneg) + c2 -= (int)(bn_sub_words(&(r[0]), &(r[0]), &(t[n]), n)); + else + c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n]), n)); + + if (c1 != 0) { + /* Add starting at r[0], could be +ve or -ve */ + i = 0; + if (c1 > 0) { + lc = c1; + do { + ll = (r[i]+lc)&BN_MASK2; + r[i++] = ll; + lc = (lc > ll); + } while (lc); + } else { + lc = -c1; + do { + ll = r[i]; + r[i++] = (ll-lc)&BN_MASK2; + lc = (lc > ll); + } while (lc); + } + } + if (c2 != 0) { + /* Add starting at r[1] */ + i = n; + if (c2 > 0) { + lc = c2; + do { + ll = (r[i]+lc)&BN_MASK2; + r[i++] = ll; + lc = (lc > ll); + } while (lc); + } else { + lc = -c2; + do { + ll = r[i]; + r[i++] = (ll-lc)&BN_MASK2; + lc = (lc > ll); + } while (lc); + } + } +} +#endif /* BN_RECURSION */ + +int +BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int top, al, bl; + BIGNUM *rr; + int ret = 0; +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + int i; +#endif +#ifdef BN_RECURSION + BIGNUM *t; + int j, k; +#endif + +#ifdef BN_COUNT + printf("BN_mul %d * %d\n", a->top, b->top); +#endif + + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al = a->top; + bl = b->top; + + if ((al == 0) || (bl == 0)) { + if (!BN_zero(r)) goto err; + return (1); + } + top = al+bl; + + BN_CTX_start(ctx); + if ((r == a) || (r == b)) { + if ((rr = BN_CTX_get(ctx)) == NULL) goto err; + } else + rr = r; + rr->neg = a->neg^b->neg; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + i = al-bl; +#endif +#ifdef BN_MUL_COMBA + if (i == 0) { + if (al == 8) { + if (bn_wexpand(rr, 16) == NULL) goto err; + rr->top = 16; + bn_mul_comba8(rr->d, a->d, b->d); + goto end; + } + } +#endif /* BN_MUL_COMBA */ +#ifdef BN_RECURSION + if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { + if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA) && bl < b->dmax) { + b->d[bl] = 0; + bl++; + i--; + } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA) && al < a->dmax) { + a->d[al] = 0; + al++; + i++; + } + if (i == 0) { + /* symmetric and > 4 */ + /* 16 or larger */ + j = BN_num_bits_word((BN_ULONG)al); + j = 1 << (j - 1); + k = j + j; + t = BN_CTX_get(ctx); + if (al == j) { + /* exact multiple */ + if (bn_wexpand(t, k*2) == NULL) goto err; + if (bn_wexpand(rr, k*2) == NULL) goto err; + bn_mul_recursive(rr->d, a->d, b->d, al, t->d); + rr->top = top; + goto end; + } + } + } +#endif /* BN_RECURSION */ + if (bn_wexpand(rr, top) == NULL) goto err; + rr->top = top; + bn_mul_normal(rr->d, a->d, al, b->d, bl); + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) +end: +#endif + bn_fix_top(rr); + if (r != rr) BN_copy(r, rr); + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +void +bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) +{ + BN_ULONG *rr; + +#ifdef BN_COUNT + printf(" bn_mul_normal %d * %d\n", na, nb); +#endif + + if (na < nb) { + int itmp; + BN_ULONG *ltmp; + + itmp = na; na = nb; nb = itmp; + ltmp = a; a = b; b = ltmp; + } + rr = &(r[na]); + rr[0] = bn_mul_words(r, a, na, b[0]); + + for (;;) { + if (--nb <= 0) return; + rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); + if (--nb <= 0) return; + rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); + if (--nb <= 0) return; + rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); + if (--nb <= 0) return; + rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); + rr += 4; + r += 4; + b += 4; + } +} + +#ifdef NOT_NEEDED_FOR_DH +void +bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +{ +#ifdef BN_COUNT + printf(" bn_mul_low_normal %d * %d\n", n, n); +#endif + bn_mul_words(r, a, n, b[0]); + + for (;;) { + if (--n <= 0) return; + bn_mul_add_words(&(r[1]), a, n, b[1]); + if (--n <= 0) return; + bn_mul_add_words(&(r[2]), a, n, b[2]); + if (--n <= 0) return; + bn_mul_add_words(&(r[3]), a, n, b[3]); + if (--n <= 0) return; + bn_mul_add_words(&(r[4]), a, n, b[4]); + r += 4; + b += 4; + } +} +#endif /* NOT_NEEDED_FOR_DH */ + +static int +bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) +{ + unsigned char *buf = NULL; + int ret = 0, bit, bytes, mask; + + if (bits == 0) { + BN_zero(rnd); + return 1; + } + + bytes = (bits + 7) / 8; + bit = (bits - 1) % 8; + mask = 0xff << (bit + 1); + + buf = (unsigned char *)OPENSSL_malloc(bytes); + if (buf == NULL) { + BNerr(BN_F_BN_RAND, ERR_R_MALLOC_FAILURE); + goto err; + } + + + assert(bn_rand_fn); + bn_rand_fn(buf, bytes); + + if (pseudorand == 2) { + /* generate patterns that are more likely to trigger BN + * library bugs + */ + int i; + unsigned char c; + + for (i = 0; i < bytes; i++) { +/* RAND_pseudo_bytes(&c, 1); */ + bn_rand_fn(&c, 1); + if (c >= 128 && i > 0) + buf[i] = buf[i-1]; + else if (c < 42) + buf[i] = 0; + else if (c < 84) + buf[i] = 255; + } + } + + if (top != -1) { + if (top) { + if (bit == 0) { + buf[0] = 1; + buf[1] |= 0x80; + } else { + buf[0] |= (3 << (bit - 1)); + } + } else { + buf[0] |= (1 << bit); + } + } + buf[0] &= ~mask; + if (bottom) /* set bottom bit if requested */ + buf[bytes-1] |= 1; + if (!BN_bin2bn(buf, bytes, rnd)) goto err; + ret = 1; +err: + if (buf != NULL) { + OPENSSL_cleanse(buf, bytes); + OPENSSL_free(buf); + } + return (ret); +} + +int +BN_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(0, rnd, bits, top, bottom); +} + +#ifdef BCMDH_TEST +int +BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(1, rnd, bits, top, bottom); +} +#endif /* BCMDH_TEST */ + +#ifdef NOT_NEEDED_FOR_DH +int +BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(2, rnd, bits, top, bottom); +} +#endif /* NOT_NEEDED_FOR_DH */ + + +#ifdef BCMDH_TEST +/* random number r: 0 <= r < range */ +static int +bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range) +{ + int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; + int n; + + if (range->neg || BN_is_zero(range)) { + BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); + return 0; + } + + n = BN_num_bits(range); /* n > 0 */ + + /* BN_is_bit_set(range, n - 1) always holds */ + + if (n == 1) { + if (!BN_zero(r)) return 0; + } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { + /* range = 100..._2, + * so 3*range ( = 11..._2) is exactly one bit longer than range + */ + do { + if (!bn_rand(r, n + 1, -1, 0)) return 0; + /* If r < 3*range, use r : = r MOD range + * (which is either r, r - range, or r - 2*range). + * Otherwise, iterate once more. + * Since 3*range = 11..._2, each iteration succeeds with + * probability >= .75. + */ + if (BN_cmp(r, range) >= 0) { + if (!BN_sub(r, r, range)) return 0; + if (BN_cmp(r, range) >= 0) + if (!BN_sub(r, r, range)) return 0; + } + } + while (BN_cmp(r, range) >= 0) + ; + } else { + do { + /* range = 11..._2 or range = 101..._2 */ + if (!bn_rand(r, n, -1, 0)) + return 0; + } while (BN_cmp(r, range) >= 0); + } + + return 1; +} +#endif /* BCMDH_TEST */ + +#ifdef NOT_NEEDED_FOR_DH +int +BN_rand_range(BIGNUM *r, BIGNUM *range) +{ + return bn_rand_range(0, r, range); +} +#endif /* NOT_NEEDED_FOR_DH */ + +#ifdef BCMDH_TEST +int +BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range) +{ + return bn_rand_range(1, r, range); +} +#endif /* BCMDH_TEST */ + +#ifdef NOT_NEEDED_FOR_DH +void +BN_RECP_CTX_init(BN_RECP_CTX *recp) +{ + BN_init(&(recp->N)); + BN_init(&(recp->Nr)); + recp->num_bits = 0; + recp->flags = 0; +} + +BN_RECP_CTX * +BN_RECP_CTX_new(void) +{ + BN_RECP_CTX *ret; + + if ((ret = (BN_RECP_CTX *)OPENSSL_malloc(sizeof(BN_RECP_CTX))) == NULL) + return (NULL); + + BN_RECP_CTX_init(ret); + ret->flags = BN_FLG_MALLOCED; + return (ret); +} + +void +BN_RECP_CTX_free(BN_RECP_CTX *recp) +{ + if (recp == NULL) + return; + + BN_free(&(recp->N)); + BN_free(&(recp->Nr)); + if (recp->flags & BN_FLG_MALLOCED) + OPENSSL_free(recp); +} + +int +BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) +{ + if (!BN_copy(&(recp->N), d)) return 0; + if (!BN_zero(&(recp->Nr))) return 0; + recp->num_bits = BN_num_bits(d); + recp->shift = 0; + return (1); +} + +int +BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *a; + const BIGNUM *ca; + + BN_CTX_start(ctx); + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if (y != NULL) { + if (x == y) { + if (!BN_sqr(a, x, ctx)) + goto err; + } else { + if (!BN_mul(a, x, y, ctx)) + goto err; + } + ca = a; + } else + ca = x; /* Just do the mod */ + + ret = BN_div_recp(NULL, r, ca, recp, ctx); +err: + BN_CTX_end(ctx); + return (ret); +} + +int +BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int i, j, ret = 0; + BIGNUM *a, *b, *d, *r; + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (dv != NULL) + d = dv; + else + d = BN_CTX_get(ctx); + if (rem != NULL) + r = rem; + else + r = BN_CTX_get(ctx); + if (a == NULL || b == NULL || d == NULL || r == NULL) + goto err; + + if (BN_ucmp(m, &(recp->N)) < 0) { + if (!BN_zero(d)) return 0; + if (!BN_copy(r, m)) return 0; + BN_CTX_end(ctx); + return (1); + } + + /* We want the remainder + * Given input of ABCDEF / ab + * we need multiply ABCDEF by 3 digests of the reciprocal of ab + * + */ + + /* i : = max(BN_num_bits(m), 2*BN_num_bits(N)) */ + i = BN_num_bits(m); + j = recp->num_bits << 1; + if (j > i) i = j; + + /* Nr : = round(2^i / N) */ + if (i != recp->shift) + recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), + i, ctx); /* BN_reciprocal returns i, or -1 for an error */ + if (recp->shift == -1) goto err; + + /* d : = |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| + * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))| + * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| + * = |m/N| + */ + if (!BN_rshift(a, m, recp->num_bits)) goto err; + if (!BN_mul(b, a, &(recp->Nr), ctx)) goto err; + if (!BN_rshift(d, b, i-recp->num_bits)) goto err; + d->neg = 0; + + if (!BN_mul(b, &(recp->N), d, ctx)) goto err; + if (!BN_usub(r, m, b)) goto err; + r->neg = 0; + + j = 0; + while (BN_ucmp(r, &(recp->N)) >= 0) { + if (j++ > 2) { + BNerr(BN_F_BN_MOD_MUL_RECIPROCAL, BN_R_BAD_RECIPROCAL); + goto err; + } + if (!BN_usub(r, r, &(recp->N))) goto err; + if (!BN_add_word(d, 1)) goto err; + } + + r->neg = BN_is_zero(r)?0:m->neg; + d->neg = m->neg^recp->N.neg; + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +/* len is the expected size of the result + * We actually calculate with an extra word of precision, so + * we can do faster division if the remainder is not required. + */ +/* r : = 2^len / m */ +int +BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) +{ + int ret = -1; + BIGNUM t; + + BN_init(&t); + + if (!BN_zero(&t)) goto err; + if (!BN_set_bit(&t, len)) goto err; + + if (!BN_div(r, NULL, &t, m, ctx)) goto err; + + ret = len; +err: + BN_free(&t); + return (ret); +} +#endif /* NOT_NEEDED_FOR_DH */ + +int +BN_lshift1(BIGNUM *r, const BIGNUM *a) +{ + register BN_ULONG *ap, *rp, t, c; + int i; + + if (r != a) { + r->neg = a->neg; + if (bn_wexpand(r, a->top+1) == NULL) return (0); + r->top = a->top; + } else { + if (bn_wexpand(r, a->top+1) == NULL) return (0); + } + ap = a->d; + rp = r->d; + c = 0; + for (i = 0; i < a->top; i++) { + t = *(ap++); + *(rp++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT)?1:0; + } + if (c) { + *rp = 1; + r->top++; + } + return (1); +} + +int +BN_rshift1(BIGNUM *r, const BIGNUM *a) +{ + BN_ULONG *ap, *rp, t, c; + int i; + + if (BN_is_zero(a)) { + BN_zero(r); + return (1); + } + if (a != r) { + if (bn_wexpand(r, a->top) == NULL) return (0); + r->top = a->top; + r->neg = a->neg; + } + ap = a->d; + rp = r->d; + c = 0; + for (i = a->top - 1; i >= 0; i--) { + t = ap[i]; + rp[i] = ((t >> 1) & BN_MASK2) | c; + c = (t & 1) ? BN_TBIT : 0; + } + bn_fix_top(r); + return (1); +} + +int +BN_lshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l; + + r->neg = a->neg; + nw = n / BN_BITS2; + if (bn_wexpand(r, a->top + nw + 1) == NULL) + return (0); + lb = n % BN_BITS2; + rb = BN_BITS2 - lb; + f = a->d; + t = r->d; + t[a->top + nw] = 0; + if (lb == 0) + for (i = a->top - 1; i >= 0; i--) + t[nw+i] = f[i]; + else + for (i = a->top-1; i >= 0; i--) { + l = f[i]; + t[nw + i + 1] |= (l >> rb) & BN_MASK2; + t[nw + i] = (l << lb) & BN_MASK2; + } + memset(t, 0, nw * sizeof(t[0])); +/* for (i = 0; i < nw; i++) + * t[i] = 0; + */ + r->top = a->top + nw + 1; + bn_fix_top(r); + return (1); +} + +int +BN_rshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, j, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, tmp; + + nw = n/BN_BITS2; + rb = n%BN_BITS2; + lb = BN_BITS2-rb; + if (nw > a->top || a->top == 0) { + BN_zero(r); + return (1); + } + if (r != a) { + r->neg = a->neg; + if (bn_wexpand(r, a->top-nw+1) == NULL) return (0); + } else { + if (n == 0) + return 1; /* or the copying loop will go berserk */ + } + + f = &(a->d[nw]); + t = r->d; + j = a->top-nw; + r->top = j; + + if (rb == 0) { + for (i = j+1; i > 0; i--) + *(t++) = *(f++); + } else { + l = *(f++); + for (i = 1; i < j; i++) { + tmp = (l >> rb)&BN_MASK2; + l = *(f++); + *(t++) = (tmp | (l << lb)) & BN_MASK2; + } + *(t++) = (l>>rb)&BN_MASK2; + } + *t = 0; + bn_fix_top(r); + return (1); +} + +/* r must not be a */ +/* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 */ +int +BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) +{ + int max, al; + int ret = 0; + BIGNUM *tmp, *rr; + +#ifdef BN_COUNT + fprintf(stderr, "BN_sqr %d * %d\n", a->top, a->top); +#endif + bn_check_top(a); + + al = a->top; + if (al <= 0) { + r->top = 0; + return (1); + } + + BN_CTX_start(ctx); + rr = (a != r) ? r : BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) goto err; + + max = (al + al); + if (bn_wexpand(rr, max + 1) == NULL) + goto err; + + if (al == 4) { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d, a->d, 4, t); +#else + bn_sqr_comba4(rr->d, a->d); +#endif + } else if (al == 8) { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d, a->d, 8, t); +#else + bn_sqr_comba8(rr->d, a->d); +#endif + } else { +#if defined(BN_RECURSION) + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2]; + bn_sqr_normal(rr->d, a->d, al, t); + } else { + int j, k; + + j = BN_num_bits_word((BN_ULONG)al); + j = 1 << (j - 1); + k = j + j; + if (al == j) { + if (bn_wexpand(tmp, k*2) == NULL) goto err; + bn_sqr_recursive(rr->d, a->d, al, tmp->d); + } else { + if (bn_wexpand(tmp, max) == NULL) goto err; + bn_sqr_normal(rr->d, a->d, al, tmp->d); + } + } +#else + if (bn_wexpand(tmp, max) == NULL) + goto err; + bn_sqr_normal(rr->d, a->d, al, tmp->d); +#endif /* BN_RECURSION */ + } + + rr->top = max; + rr->neg = 0; + if ((max > 0) && (rr->d[max-1] == 0)) rr->top--; + if (rr != r) BN_copy(r, rr); + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +/* tmp must have 2*n words */ +void +bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp) +{ + int i, j, max; + const BN_ULONG *ap; + BN_ULONG *rp; + + max = n*2; + ap = a; + rp = r; + rp[0] = rp[max-1] = 0; + rp++; + j = n; + + if (--j > 0) { + ap++; + rp[j] = bn_mul_words(rp, ap, j, ap[-1]); + rp += 2; + } + + for (i = n - 2; i > 0; i--) { + j--; + ap++; + rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]); + rp += 2; + } + + bn_add_words(r, r, r, max); + + /* There will not be a carry */ + + bn_sqr_words(tmp, a, n); + + bn_add_words(r, r, tmp, max); +} + +#ifdef BN_RECURSION +/* r is 2*n words in size, + * a and b are both n words in size. (There's not actually a 'b' here ...) + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void +bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t) +{ + int n = n2/2; + int zero, c1; + BN_ULONG ln, lo, *p; + +#ifdef BN_COUNT + fprintf(stderr, " bn_sqr_recursive %d * %d\n", n2, n2); +#endif + if (n2 == 4) { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 4, t); +#else + bn_sqr_comba4(r, a); +#endif + return; + } else if (n2 == 8) { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 8, t); +#else + bn_sqr_comba8(r, a); +#endif + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) { + bn_sqr_normal(r, a, n2, t); + return; + } + /* r = (a[0]-a[1])*(a[1]-a[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + zero = 0; + if (c1 > 0) + bn_sub_words(t, a, &(a[n]), n); + else if (c1 < 0) + bn_sub_words(t, &(a[n]), a, n); + else + zero = 1; + + /* The result will always be negative unless it is zero */ + p = &(t[n2*2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]), t, n, p); + else + memset(&(t[n2]), 0, n2*sizeof(BN_ULONG)); + bn_sqr_recursive(r, a, n, p); + bn_sqr_recursive(&(r[n2]), &(a[n]), n, p); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + /* t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n+n2]); + lo = *p; + ln = (lo+c1)&BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo+1)&BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} +#endif /* BN_RECURSION */ + +#ifdef BCMDH_TEST +BN_ULONG +BN_mod_word(const BIGNUM *a, BN_ULONG w) +{ +#ifndef BN_LLONG + BN_ULONG ret = 0; +#else + BN_ULLONG ret = 0; +#endif + int i; + + w &= BN_MASK2; + for (i = a->top-1; i >= 0; i--) { +#ifndef BN_LLONG + ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; + ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; +#else + ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) | a->d[i]) % (BN_ULLONG)w); +#endif + } + return ((BN_ULONG)ret); +} +#endif /* BCMDH_TEST */ + +#ifdef NOT_NEEDED_FOR_DH +BN_ULONG +BN_div_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ret; + int i; + + if (a->top == 0) return (0); + ret = 0; + w &= BN_MASK2; + for (i = a->top-1; i >= 0; i--) { + BN_ULONG l, d; + + l = a->d[i]; + d = bn_div_words(ret, l, w); + ret = (l-((d*w)&BN_MASK2))&BN_MASK2; + a->d[i] = d; + } + if ((a->top > 0) && (a->d[a->top-1] == 0)) + a->top--; + return (ret); +} +#endif /* NOT_NEEDED_FOR_DH */ + +int +BN_add_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG l; + int i; + + if (a->neg) { + a->neg = 0; + i = BN_sub_word(a, w); + if (!BN_is_zero(a)) + a->neg = !(a->neg); + return (i); + } + w &= BN_MASK2; + if (bn_wexpand(a, a->top+1) == NULL) return (0); + i = 0; + for (;;) { + if (i >= a->top) + l = w; + else + l = (a->d[i]+(BN_ULONG)w)&BN_MASK2; + a->d[i] = l; + if (w > l) + w = 1; + else + break; + i++; + } + if (i >= a->top) + a->top++; + return (1); +} + +int +BN_sub_word(BIGNUM *a, BN_ULONG w) +{ + int i; + + if (BN_is_zero(a) || a->neg) { + a->neg = 0; + i = BN_add_word(a, w); + a->neg = 1; + return (i); + } + + w &= BN_MASK2; + if ((a->top == 1) && (a->d[0] < w)) { + a->d[0] = w-a->d[0]; + a->neg = 1; + return (1); + } + i = 0; + for (;;) { + if (a->d[i] >= w) { + a->d[i] -= w; + break; + } else { + a->d[i] = (a->d[i]-w)&BN_MASK2; + i++; + w = 1; + } + } + if ((a->d[i] == 0) && (i == (a->top-1))) + a->top--; + return (1); +} + +int +BN_mul_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ll; + + w &= BN_MASK2; + if (a->top) { + if (w == 0) + BN_zero(a); + else { + ll = bn_mul_words(a->d, a->d, a->top, w); + if (ll) { + if (bn_wexpand(a, a->top+1) == NULL) return (0); + a->d[a->top++] = ll; + } + } + } + return (1); +} + +#ifdef BCMDH_TEST +/* The quick sieve algorithm approach to weeding out primes is + * Philip Zimmermann's, as implemented in PGP. I have had a read of + * his comments and implemented my own version. + */ + +#ifndef EIGHT_BIT +#define NUMPRIMES 2048 +#else +#define NUMPRIMES 54 +#endif +static const unsigned int primes[NUMPRIMES] = +{ + 2, 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, +#ifndef EIGHT_BIT + 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, + 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, + 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, + 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, + 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, + 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, + 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, + 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, + 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, + 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, + 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, + 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, + 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, + 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, + 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, + 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, + 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, + 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, + 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, + 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, + 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, + 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, + 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, + 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, + 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, + 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, + 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, + 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, + 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, + 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, + 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, + 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, + 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, + 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, + 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, + 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, + 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, + 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, + 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, + 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, + 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, + 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, + 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, + 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, + 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, + 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, + 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, + 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, + 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, + 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, + 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, + 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, + 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, + 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, + 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, + 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, + 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, + 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, + 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, + 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, + 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, + 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, + 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, + 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, + 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, + 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, + 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, + 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, + 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, + 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, + 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, + 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, + 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, + 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, + 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, + 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, + 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, + 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, + 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, + 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, + 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, + 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, + 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, + 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, + 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, + 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, + 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, + 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, + 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, + 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, + 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, + 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, + 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, + 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, + 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, + 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, + 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, + 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, + 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, + 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, + 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, + 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, + 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, + 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, + 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, + 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, + 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, + 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, + 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, + 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, + 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, + 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, + 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, + 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, + 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, + 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, + 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, + 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, + 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, + 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, + 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, + 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, + 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, + 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, + 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, + 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, + 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, + 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, + 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, + 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, + 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, + 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, + 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, + 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, + 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, + 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, + 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, + 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, + 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, + 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, + 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, + 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, + 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, + 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, + 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, + 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, + 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, + 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863 +#endif /* !EIGHT_BIT */ +}; + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont); +static int probable_prime(BIGNUM *rnd, int bits); +static int probable_prime_dh(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); +static int probable_prime_dh_safe(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); + +BIGNUM * +BN_generate_prime(BIGNUM *ret, int bits, int safe, const BIGNUM *add, const BIGNUM *rem, + void (*callback)(int, int, void *), void *cb_arg) +{ + BIGNUM *rnd = NULL; + BIGNUM t; + int found = 0; + int i, j, c1 = 0; + BN_CTX *ctx; + int checks = BN_prime_checks_for_size(bits); + + BN_init(&t); + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; + if (ret == NULL) { + if ((rnd = BN_new()) == NULL) goto err; + } else + rnd = ret; +loop: + /* make a random number and set the top and bottom bits */ + if (add == NULL) { + if (!probable_prime(rnd, bits)) goto err; + } else { + if (safe) { + if (!probable_prime_dh_safe(rnd, bits, add, rem, ctx)) + goto err; + } else { + if (!probable_prime_dh(rnd, bits, add, rem, ctx)) + goto err; + } + } + /* if (BN_mod_word(rnd, (BN_ULONG)3) == 1) goto loop; */ + if (callback != NULL) + callback(0, c1++, cb_arg); + + if (!safe) { + i = BN_is_prime_fasttest(rnd, checks, callback, ctx, cb_arg, 0); + if (i == -1) goto err; + if (i == 0) goto loop; + } else { + /* for "safe prime" generation, + * check that (p-1)/2 is prime. + * Since a prime is odd, We just + * need to divide by 2 + */ + if (!BN_rshift1(&t, rnd)) goto err; + + for (i = 0; i < checks; i++) { + j = BN_is_prime_fasttest(rnd, 1, callback, ctx, cb_arg, 0); + if (j == -1) goto err; + if (j == 0) goto loop; + + j = BN_is_prime_fasttest(&t, 1, callback, ctx, cb_arg, 0); + if (j == -1) goto err; + if (j == 0) goto loop; + + if (callback != NULL) callback(2, c1-1, cb_arg); + /* We have a safe prime test pass */ + } + } + /* we have a prime :-) */ + found = 1; +err: + if (!found && (ret == NULL) && (rnd != NULL)) BN_free(rnd); + BN_free(&t); + if (ctx != NULL) BN_CTX_free(ctx); + return (found ? rnd : NULL); +} + +int +BN_is_prime(const BIGNUM *a, int checks, void (*callback)(int, int, void *), + BN_CTX *ctx_passed, void *cb_arg) +{ + return BN_is_prime_fasttest(a, checks, callback, ctx_passed, cb_arg, 0); +} + +int +BN_is_prime_fasttest(const BIGNUM *a, int checks, void (*callback)(int, int, void *), + BN_CTX *ctx_passed, void *cb_arg, int do_trial_division) +{ + int i, j, ret = -1; + int k; + BN_CTX *ctx = NULL; + BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ + BN_MONT_CTX *mont = NULL; + const BIGNUM *A = NULL; + + if (BN_cmp(a, BN_value_one()) <= 0) + return 0; + + if (checks == BN_prime_checks) + checks = BN_prime_checks_for_size(BN_num_bits(a)); + + /* first look for small factors */ + if (!BN_is_odd(a)) + return 0; + if (do_trial_division) { + for (i = 1; i < NUMPRIMES; i++) + if (BN_mod_word(a, primes[i]) == 0) + return 0; + if (callback != NULL) + callback(1, -1, cb_arg); + } + + if (ctx_passed != NULL) + ctx = ctx_passed; + else + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + + /* A : = abs(a) */ + if (a->neg) { + BIGNUM *t; + if ((t = BN_CTX_get(ctx)) == NULL) goto err; + BN_copy(t, a); + t->neg = 0; + A = t; + } else + A = a; + A1 = BN_CTX_get(ctx); + A1_odd = BN_CTX_get(ctx); + check = BN_CTX_get(ctx); + if (check == NULL) goto err; + + /* compute A1 : = A - 1 */ + if (!BN_copy(A1, A)) + goto err; + if (!BN_sub_word(A1, 1)) + goto err; + if (BN_is_zero(A1)) { + ret = 0; + goto err; + } + + /* write A1 as A1_odd * 2^k */ + k = 1; + while (!BN_is_bit_set(A1, k)) + k++; + if (!BN_rshift(A1_odd, A1, k)) + goto err; + + /* Montgomery setup for computations mod A */ + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, A, ctx)) + goto err; + + for (i = 0; i < checks; i++) { + if (!BN_pseudo_rand_range(check, A1)) + goto err; + if (!BN_add_word(check, 1)) + goto err; + /* now 1 <= check < A */ + + j = witness(check, A, A1, A1_odd, k, ctx, mont); + if (j == -1) goto err; + if (j) { + ret = 0; + goto err; + } + if (callback != NULL) + callback(1, i, cb_arg); + } + ret = 1; +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + if (ctx_passed == NULL) + BN_CTX_free(ctx); + } + if (mont != NULL) + BN_MONT_CTX_free(mont); + + return (ret); +} + +static int +witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) +{ + if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w : = w^a1_odd mod a */ + return -1; + if (BN_is_one(w)) + return 0; /* probably prime */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + while (--k) { + if (!BN_mod_mul(w, w, w, a, ctx)) /* w : = w^2 mod a */ + return -1; + if (BN_is_one(w)) + return 1; /* 'a' is composite, otherwise a previous 'w' would + * have been == -1 (mod 'a') + */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + } + /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', + * and it is neither -1 nor +1 -- so 'a' cannot be prime + */ + return 1; +} + +static int +probable_prime(BIGNUM *rnd, int bits) +{ + int i; + BN_ULONG mods[NUMPRIMES]; + BN_ULONG delta, d; + +again: + if (!BN_rand(rnd, bits, 1, 1)) return (0); + /* we now have a random number 'rand' to test. */ + for (i = 1; i < NUMPRIMES; i++) + mods[i] = BN_mod_word(rnd, (BN_ULONG)primes[i]); + delta = 0; +loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that rnd is not a prime and also + * that gcd(rnd-1, primes) == 1 (except for 2) + */ + if (((mods[i]+delta)%primes[i]) <= 1) { + d = delta; + delta += 2; + /* perhaps need to check for overflow of + * delta (but delta can be up to 2^32) + * 21-May-98 eay - added overflow check + */ + if (delta < d) goto again; + goto loop; + } + } + if (!BN_add_word(rnd, delta)) return (0); + return (1); +} + +static int +probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *t1; + + BN_CTX_start(ctx); + if ((t1 = BN_CTX_get(ctx)) == NULL) goto err; + + if (!BN_rand(rnd, bits, 0, 1)) + goto err; + + /* we need ((rnd-rem) % add) == 0 */ + + if (!BN_mod(t1, rnd, add, ctx)) + goto err; + if (!BN_sub(rnd, rnd, t1)) + goto err; + if (rem == NULL) { + if (!BN_add_word(rnd, 1)) + goto err; + } else { + if (!BN_add(rnd, rnd, rem)) + goto err; + } + + /* we now have a random number 'rand' to test. */ + + loop: for (i = 1; i < NUMPRIMES; i++) { + /* check that rnd is a prime */ + if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) { + if (!BN_add(rnd, rnd, add)) goto err; + goto loop; + } + } + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} + +static int +probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, const BIGNUM *rem, BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *t1, *qadd, *q; + + bits--; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + qadd = BN_CTX_get(ctx); + if (qadd == NULL) goto err; + + if (!BN_rshift1(qadd, padd)) goto err; + + if (!BN_rand(q, bits, 0, 1)) goto err; + + /* we need ((rnd-rem) % add) == 0 */ + if (!BN_mod(t1, q, qadd, ctx)) goto err; + if (!BN_sub(q, q, t1)) goto err; + if (rem == NULL) { + if (!BN_add_word(q, 1)) goto err; + } else { + if (!BN_rshift1(t1, rem)) goto err; + if (!BN_add(q, q, t1)) goto err; + } + + /* we now have a random number 'rand' to test. */ + if (!BN_lshift1(p, q)) goto err; + if (!BN_add_word(p, 1)) goto err; + +loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that p and q are prime */ + /* check that for p and q + * gcd(p-1, primes) == 1 (except for 2) + */ + if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) || + (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) { + if (!BN_add(p, p, padd)) goto err; + if (!BN_add(q, q, qadd)) goto err; + goto loop; + } + } + ret = 1; +err: + BN_CTX_end(ctx); + return (ret); +} +#endif /* BCMDH_TEST */ diff --git a/release/src-rt/bcmcrypto/bn_lcl.h b/release/src-rt/bcmcrypto/bn_lcl.h new file mode 100755 index 0000000000..56c8f51203 --- /dev/null +++ b/release/src-rt/bcmcrypto/bn_lcl.h @@ -0,0 +1,451 @@ +/* + * bn_lcl.h: Big Number local header file. + * + * Code copied from openssl distribution and + * Modified just enough so that compiles and runs standalone + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: bn_lcl.h,v 1.3 2006-06-15 10:09:43 Exp $ + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_BN_LCL_H +#define HEADER_BN_LCL_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Used for temp variables */ +#define BN_CTX_NUM 32 +#define BN_CTX_NUM_POS 12 +struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM]; + int flags; + int depth; + int pos[BN_CTX_NUM_POS]; + int too_many; + } /* BN_CTX */; + + +/* + * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions + * + * + * For window size 'w' (w >= 2) and a random 'b' bits exponent, + * the number of multiplications is a constant plus on average + * + * 2^(w-1) + (b-w)/(w+1); + * + * here 2^(w-1) is for precomputing the table (we actually need + * entries only for windows that have the lowest bit set), and + * (b-w)/(w+1) is an approximation for the expected number of + * w-bit windows, not counting the first one. + * + * Thus we should use + * + * w >= 6 if b > 671 + * w = 5 if 671 > b > 239 + * w = 4 if 239 > b > 79 + * w = 3 if 79 > b > 23 + * w <= 2 if 23 > b + * + * (with draws in between). Very small exponents are often selected + * with low Hamming weight, so we use w = 1 for b <= 23. + */ +#define BN_window_bits_for_exponent_size(b) \ + ((b) > 671 ? 6 : \ + (b) > 239 ? 5 : \ + (b) > 79 ? 4 : \ + (b) > 23 ? 3 : 1) + + +/* Pentium pro 16, 16, 16, 32, 64 */ +/* Alpha 16, 16, 16, 16.64 */ +#define BN_MULL_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */ +#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */ +#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */ + +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +/* + * BN_UMULT_HIGH section. + * + * No, I'm not trying to overwhelm you when stating that the + * product of N-bit numbers is 2*N bits wide:-) No, I don't expect + * you to be impressed when I say that if the compiler doesn't + * support 2*N integer type, then you have to replace every N*N + * multiplication with 4 (N/2)*(N/2) accompanied by some shifts + * and additions which unavoidably results in severe performance + * penalties. Of course provided that the hardware is capable of + * producing 2*N result... That's when you normally start + * considering assembler implementation. However! It should be + * pointed out that some CPUs (most notably Alpha, PowerPC and + * upcoming IA-64 family:-) provide *separate* instruction + * calculating the upper half of the product placing the result + * into a general purpose register. Now *if* the compiler supports + * inline assembler, then it's not impossible to implement the + * "bignum" routines (and have the compiler optimize 'em) + * exhibiting "native" performance in C. That's what BN_UMULT_HIGH + * macro is about:-) + * + * + */ +# if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) +# if defined(__DECC) +# include +# define BN_UMULT_HIGH(a, b) (BN_ULONG)asm("umulh %a0, %a1, %v0", (a), (b)) +# elif defined(__GNUC__) +# define BN_UMULT_HIGH(a, b) ({ \ + register BN_ULONG ret; \ + asm("umulh %1, %2, %0" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG) +# if defined(__GNUC__) +# define BN_UMULT_HIGH(a, b) ({ \ + register BN_ULONG ret; \ + asm("mulhdu %0, %1, %2" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG) +# if defined(__GNUC__) +# define BN_UMULT_HIGH(a, b) ({ \ + register BN_ULONG ret, discard; \ + asm("mulq %3" \ + : "=a"(discard), "=d"(ret) \ + : "a"(a), "g"(b) \ + : "cc"); \ + ret; }) +# define BN_UMULT_LOHI(low, high, a, b) \ + asm("mulq %3" \ + : "=a"(low), "=d"(high) \ + : "a"(a), "g"(b) \ + : "cc"); +# endif +# endif /* cpu */ +#endif /* OPENSSL_NO_ASM */ + +/************************************************************* + * Using the long long type + */ +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +/* This is used for internal error checking and is not normally used */ +#ifdef BN_DEBUG +# include +# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax); +#else +# define bn_check_top(a) +#endif + +/* This macro is to add extra stuff for development checking */ +#ifdef BN_DEBUG +#define bn_set_max(r) ((r)->max = (r)->top, BN_set_flags((r), BN_FLG_STATIC_DATA)) +#else +#define bn_set_max(r) +#endif + +/* These macros are used to 'take' a section of a bignum for read only use */ +#define bn_set_low(r, a, n) { \ + (r)->top = ((a)->top > (n))?(n):(a)->top; \ + (r)->d = (a)->d; \ + (r)->neg = (a)->neg; \ + (r)->flags |= BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ +} + +#define bn_set_high(r, a, n) { \ + if ((a)->top > (n)) { \ + (r)->top = (a)->top-n; \ + (r)->d = &((a)->d[n]); \ + } else \ + (r)->top = 0; \ + (r)->neg = (a)->neg; \ + (r)->flags |= BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ +} + +#ifdef BN_LLONG +#define mul_add(r, a, w, c) { \ + BN_ULLONG t; \ + t = (BN_ULLONG)w * (a) + (r) + (c); \ + (r) = Lw(t); \ + (c) = Hw(t); \ +} + +#define mul(r, a, w, c) { \ + BN_ULLONG t; \ + t = (BN_ULLONG)w * (a) + (c); \ + (r) = Lw(t); \ + (c) = Hw(t); \ +} + +#define sqr(r0, r1, a) { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(a)*(a); \ + (r0) = Lw(t); \ + (r1) = Hw(t); \ +} + +#elif defined(BN_UMULT_HIGH) +#define mul_add(r, a, w, c) { \ + BN_ULONG high, low, ret, tmp = (a); \ + ret = (r); \ + high = BN_UMULT_HIGH(w, tmp); \ + ret += (c); \ + low = (w) * tmp; \ + (c) = (ret < (c)) ? 1 : 0; \ + (c) += high; \ + ret += low; \ + (c) += (ret < low) ? 1 : 0; \ + (r) = ret; \ +} + +#define mul(r, a, w, c) { \ + BN_ULONG high, low, ret, ta = (a); \ + low = (w) * ta; \ + high = BN_UMULT_HIGH(w, ta); \ + ret = low + (c); \ + (c) = high; \ + (c) += (ret < low) ? 1 : 0; \ + (r) = ret; \ +} + +#define sqr(r0, r1, a) { \ + BN_ULONG tmp = (a); \ + (r0) = tmp * tmp; \ + (r1) = BN_UMULT_HIGH(tmp, tmp); \ +} + +#else +/* No long long type */ + +#define LBITS(a) ((a) & BN_MASK2l) +#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l) +#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2) + +#define LLBITS(a) ((a) & BN_MASKl) +#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl) +#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2) + +#define mul64(l, h, bl, bh) { \ + BN_ULONG m, m1, lt, ht; \ + lt = l; \ + ht = h; \ + m = (bh) * (lt); \ + lt = (bl) * (lt); \ + m1 = (bl) * (ht); \ + ht = (bh) * (ht); \ + m = (m + m1) & BN_MASK2; \ + if (m < m1) \ + ht += L2HBITS((BN_ULONG)1); \ + ht += HBITS(m); \ + m1 = L2HBITS(m); \ + lt = (lt + m1) & BN_MASK2; \ + if (lt < m1) \ + ht++; \ + (l) = lt; \ + (h) = ht; \ +} + +#define sqr64(lo, ho, in) { \ + BN_ULONG l, h, m; \ + h = (in); \ + l = LBITS(h); \ + h = HBITS(h); \ + m = (l) * (h); \ + l *= l; \ + h *= h; \ + h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \ + m = (m & BN_MASK2l) << (BN_BITS4 + 1); \ + l = (l + m) & BN_MASK2; \ + if (l < m) \ + h++; \ + (lo) = l; \ + (ho) = h; \ +} + +#define mul_add(r, a, bl, bh, c) { \ + BN_ULONG l, h; \ + h = (a); \ + l = LBITS(h); \ + h = HBITS(h); \ + mul64(l, h, (bl), (bh)); \ + /* non-multiply part */ \ + l = (l + (c)) & BN_MASK2; \ + if (l < (c)) \ + h++; \ + (c) = (r); \ + l = (l + (c)) & BN_MASK2; \ + if (l < (c)) \ + h++; \ + (c) = h & BN_MASK2; \ + (r) = l; \ +} + +#define mul(r, a, bl, bh, c) { \ + BN_ULONG l, h; \ + h = (a); \ + l = LBITS(h); \ + h = HBITS(h); \ + mul64(l, h, (bl), (bh)); \ + /* non-multiply part */ \ + l += (c); \ + if ((l & BN_MASK2) < (c)) \ + h++; \ + (c) = h & BN_MASK2; \ + (r) = l & BN_MASK2; \ +} +#endif /* !BN_LLONG */ + +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb); +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp); +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a); +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a); +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n); +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); +void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t); +void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); +void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + BN_ULONG *t); +void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2, + BN_ULONG *t); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_BN_LCL_H */ diff --git a/release/src-rt/bcmcrypto/prebuilt/.dummy b/release/src-rt/bcmcrypto/ccx.c old mode 100644 new mode 100755 similarity index 100% copy from release/src-rt/bcmcrypto/prebuilt/.dummy copy to release/src-rt/bcmcrypto/ccx.c diff --git a/release/src-rt/bcmcrypto/ccx.ref b/release/src-rt/bcmcrypto/ccx.ref new file mode 100755 index 0000000000..1c33a4e450 --- /dev/null +++ b/release/src-rt/bcmcrypto/ccx.ref @@ -0,0 +1,171 @@ +#ifdef BCMCCX +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC FF FF FF FF FF FF A0 38 00 01 15 00 EB B1 C7 6A B1 96 B2 16 58 C4 04 5E 2D 6A F3 4B 92 EB FC FC ED 70 98 D0 64 6C 5E BB 1A DD D4 2A 26 2A 8B EF C2 41 67 75 9D FB FE 5D 4E CA A0 45 6D 7C 36 22 22 7D D0 BD 09 16 1D E6 41 D9 94 BE 9B 53 C5 CB +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 15 E6 8B D6 03 23 0B 6A 60 B9 F4 EB 46 99 +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC FF FF FF FF FF FF A0 38 00 01 15 00 AA AA 03 00 40 96 00 02 2F F1 C0 A6 00 00 00 C0 08 06 00 01 08 00 06 04 00 01 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 A1 2C EE 14 21 BD D8 23 21 BD A8 AC 52 E1 01 00 00 00 28 AC 0F 82 46 86 F9 D9 +==== Original MSDU ==== +DA: FF FF FF FF FF FF +SA: 00 40 96 28 8D DC +Payload: 08 06 00 01 08 00 06 04 00 01 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 A1 2C EE 14 21 BD D8 23 21 BD A8 AC 52 E1 01 00 00 00 28 AC 0F 82 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 00 00 FF FF FF FF FF FF 00 40 96 21 DC 83 00 40 96 28 8D DC 60 2C 00 00 62 00 46 65 A8 0F 86 59 F8 57 8E 51 D5 A5 D6 FE D1 40 2A 0E 28 E1 DA AE 2C 90 45 05 7B F1 00 FD AD ED 8F 09 F3 86 81 6B 24 BE 31 36 CA 54 29 54 AA 61 1C 7D C9 F4 89 EA 71 FF 55 03 7F 8A CC 48 77 01 CA 0F 89 2C +==== CK (basic CKIP key) ==== +12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 +==== PK (permuted key) ==== +00 00 62 00 9E 5C 91 78 08 9C 36 DE 8F 3B 5F 65 +==== 802.11 packet decrypted ==== +08 42 00 00 FF FF FF FF FF FF 00 40 96 21 DC 83 00 40 96 28 8D DC 60 2C 00 00 62 00 AA AA 03 00 40 96 00 02 73 34 88 C1 00 00 00 AF 08 06 00 01 08 00 06 04 00 01 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 A1 2C EE 14 21 BD D8 23 21 BD A8 AC 52 E1 01 00 00 00 28 AC 0F 82 B4 DE 39 20 +==== Original MSDU ==== +DA: FF FF FF FF FF FF +SA: 00 40 96 28 8D DC +Payload: 08 06 00 01 08 00 06 04 00 01 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 A1 2C EE 14 21 BD D8 23 21 BD A8 AC 52 E1 01 00 00 00 28 AC 0F 82 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 70 2C 00 00 63 C0 FF 46 41 BB 38 5F C1 06 32 3F 27 B5 5B 2E 49 EB B7 11 AC AA B5 50 07 0F 6D 41 86 F3 06 A8 8F 84 DF 54 72 1F D3 21 EF 38 77 72 A9 4B 70 4F 02 4C 15 D5 89 3A 45 08 D4 F4 0B C7 F5 E8 DE 73 FE 5A E9 58 93 C0 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 63 93 42 80 56 4E C0 8E BD 8A 37 F8 52 87 +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 70 2C 00 00 63 C0 AA AA 03 00 40 96 00 02 A6 97 2C 66 00 00 00 41 08 06 00 01 08 00 06 04 00 02 00 40 96 12 CE 40 A1 2C EE 14 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B0 4E DB EA +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 06 00 01 08 00 06 04 00 02 00 40 96 12 CE 40 A1 2C EE 14 00 40 96 28 8D DC A1 2C EE 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +================================================================ +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 B0 38 00 01 16 00 5A 29 07 E8 B3 EE 6C BD CA 57 79 7E 24 45 C4 E7 0D D7 82 D0 8E 24 3D B9 60 BC E2 1C D4 59 9F FF A6 F1 60 62 F4 B8 22 BB 5D DA A0 0B 7D 7C 28 9F 11 03 8C 2C AD 84 BA 31 09 F6 B0 F4 5A 5C A4 77 6D B8 0C 1B 6A 7A B4 F8 53 C0 8C 21 7A AF 6D A3 8E 08 1F 7E 43 15 EB AC 26 04 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 16 C2 09 BC 35 3C 7E A0 42 8F 3C C0 39 B1 +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 B0 38 00 01 16 00 AA AA 03 00 40 96 00 02 43 FC D0 96 00 00 00 C2 08 00 45 00 00 44 45 6D 00 00 80 01 D6 DA A1 2C EE 03 A1 2C EE 14 08 00 28 A2 06 00 69 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 67 5A D5 7F +==== Original MSDU ==== +DA: 00 40 96 12 CE 40 +SA: 00 40 96 28 8D DC +Payload: 08 00 45 00 00 44 45 6D 00 00 80 01 D6 DA A1 2C EE 03 A1 2C EE 14 08 00 28 A2 06 00 69 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 80 2C 00 00 64 C0 3D D2 7E B5 8B 76 63 BE AD AA BA 8B D7 7D 29 63 FC 49 4F 48 FC 3F 86 75 33 2B 52 6F 78 81 63 67 BE FE 89 EE D8 16 99 FB A3 0A 8D 1E A0 68 B0 FF 7A FE 21 D2 1D 14 CC 24 74 A3 C1 7E 04 C9 C0 D0 C2 26 25 D8 5B 2C 6C 42 E3 25 10 35 85 97 02 10 B6 D2 9B FC 6B 0F 95 C7 4C DB +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 64 86 D0 75 6D A7 39 E8 33 D1 BB BA 9C 4B +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 80 2C 00 00 64 C0 AA AA 03 00 40 96 00 02 7D FB 95 B2 00 00 00 43 08 00 45 00 00 44 00 08 00 00 80 01 1C 40 A1 2C EE 14 A1 2C EE 03 00 00 30 A2 06 00 69 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 96 00 88 09 +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 00 45 00 00 44 00 08 00 00 80 01 1C 40 A1 2C EE 14 A1 2C EE 03 00 00 30 A2 06 00 69 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 +================================================================ +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 C0 38 00 01 17 00 EB 87 DA 4A 03 77 92 B5 E6 B7 66 F6 9B 21 22 45 80 ED 42 E9 A0 3E 18 46 1F 1F 4B 32 D0 E4 60 9E 0F 31 83 0C 64 13 B1 C3 D8 35 C3 2B 32 67 24 40 F2 0B 08 8A 43 E2 93 82 6B C2 8B 4C 83 FA 61 4C 1E D3 7B F9 0A 8A 6F C9 D8 A9 D8 06 5C 90 18 4A CC A9 F9 53 1A F7 90 57 8B 84 3A +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 17 EB BC 6E B5 1B EF 55 A7 1A DD D8 44 4D +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 C0 38 00 01 17 00 AA AA 03 00 40 96 00 02 8D 47 6D B7 00 00 00 C4 08 00 45 00 00 45 45 6E 00 00 80 01 D6 D8 A1 2C EE 03 A1 2C EE 14 08 00 B5 A1 06 00 6A 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 5E 17 97 C2 +==== Original MSDU ==== +DA: 00 40 96 12 CE 40 +SA: 00 40 96 28 8D DC +Payload: 08 00 45 00 00 45 45 6E 00 00 80 01 D6 D8 A1 2C EE 03 A1 2C EE 14 08 00 B5 A1 06 00 6A 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 F0 2E 00 00 65 C0 43 8F AC C7 F2 78 AF 25 73 09 6C DF E8 51 D0 D8 64 51 0D D1 44 4F E8 15 1F 87 AE A2 FC 2E 45 AB 0F 88 87 6A B6 E2 FF C7 8B 41 C3 80 9A 61 85 13 3A 99 1E AF FF DB 96 07 6E D1 30 70 E0 10 81 A0 02 A4 16 FC 46 17 A1 C9 BF 17 4B 5E 7B 94 6B 09 8F 0B 8A EE 56 BF 6C 79 D5 A0 19 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 65 66 21 F2 41 13 D3 78 07 9D 04 F7 A9 D9 +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 F0 2E 00 00 65 C0 AA AA 03 00 40 96 00 02 C7 46 32 D3 00 00 00 45 08 00 45 00 00 45 00 09 00 00 80 01 1C 3E A1 2C EE 14 A1 2C EE 03 00 00 BD A1 06 00 6A 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 A2 55 9D C8 +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 00 45 00 00 45 00 09 00 00 80 01 1C 3E A1 2C EE 14 A1 2C EE 03 00 00 BD A1 06 00 6A 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 +================================================================ +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 D0 38 00 01 18 00 EB 88 BD CE 5D 37 D5 AD 0A 99 49 56 E2 59 4E BB 14 C0 15 0E C0 48 FD CC 0F A8 2A 3D F0 3F BF AE CD B9 53 26 9B 43 44 76 40 B2 CC DA 90 16 D0 1B 65 C2 41 2F C0 07 95 41 00 94 32 14 DD 74 BA D8 D6 A5 39 0B F5 50 0C A5 95 DB 7C D3 AB F4 F4 36 B7 E9 8C F5 0F FA F1 6A B6 62 14 6C +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 18 6C 44 FB 99 8F 7D 96 84 E0 66 89 A6 E1 +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 D0 38 00 01 18 00 AA AA 03 00 40 96 00 02 BC C2 23 5E 00 00 00 C6 08 00 45 00 00 46 45 6F 00 00 80 01 D6 D6 A1 2C EE 03 A1 2C EE 14 08 00 B4 2E 06 00 6B 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 68 4C FC 9F +==== Original MSDU ==== +DA: 00 40 96 12 CE 40 +SA: 00 40 96 28 8D DC +Payload: 08 00 45 00 00 46 45 6F 00 00 80 01 D6 D6 A1 2C EE 03 A1 2C EE 14 08 00 B4 2E 06 00 6B 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 F0 2F 00 00 66 C0 C3 05 B8 5F 71 12 85 8E 89 4D 59 E0 62 5A F3 7A 77 3F 11 6E C2 9F 66 C3 2B 49 01 22 7F 61 CF 29 58 22 9D 50 CC 34 D0 56 B7 0E 98 E4 4A 47 1D D6 34 0B A7 0E 96 94 F0 39 CF 2E EF E3 63 57 D5 5D BA D0 59 DE 53 C3 9B 8A 5C 6B 1F A4 6F 35 A0 2C 61 7A 1D B9 B4 C2 29 31 F1 BA C8 BA +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 66 DF BF A5 46 6C 7C DC A4 61 B1 D5 94 E6 +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 F0 2F 00 00 66 C0 AA AA 03 00 40 96 00 02 F6 C0 E8 7A 00 00 00 47 08 00 45 00 00 46 00 0A 00 00 80 01 1C 3C A1 2C EE 14 A1 2C EE 03 00 00 BC 2E 06 00 6B 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 01 72 E9 9B +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 00 45 00 00 46 00 0A 00 00 80 01 1C 3C A1 2C EE 14 A1 2C EE 03 00 00 BC 2E 06 00 6B 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 +================================================================ +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 E0 38 00 01 19 00 F6 FF DA 8C 66 09 9F FD 7D 87 D8 AB 17 D6 30 32 C8 C0 0A 2B B5 85 CE 3E D1 EB AE A2 93 0E 43 D7 28 DB 86 5B 80 88 36 9F 7C 8D 01 6E 2A 58 5F CD E1 1C E4 D8 E8 92 43 22 DE F6 CA BA 48 C6 25 15 CB C5 2F FE 5B 90 C0 DE 54 C4 7D 4D DA 34 28 A2 DE 09 AD F3 A9 B8 64 2E 8C C8 CC A7 E1 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 19 C4 B0 7E CA C9 D4 51 19 F2 F1 30 6C 2E +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 E0 38 00 01 19 00 AA AA 03 00 40 96 00 02 D6 0A 50 C0 00 00 00 C8 08 00 45 00 00 47 45 70 00 00 80 01 D6 D4 A1 2C EE 03 A1 2C EE 14 08 00 3F 2E 06 00 6C 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 17 59 B2 64 +==== Original MSDU ==== +DA: 00 40 96 12 CE 40 +SA: 00 40 96 28 8D DC +Payload: 08 00 45 00 00 47 45 70 00 00 80 01 D6 D4 A1 2C EE 03 A1 2C EE 14 08 00 3F 2E 06 00 6C 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 C0 30 00 00 67 C0 65 8D 3A 72 0D 34 3B 88 5E C7 37 64 69 77 C4 07 B3 B1 A5 40 56 DE 8E E8 AE 5B 5C 1C D7 39 31 17 27 7E 3D 0C 41 8E 2E 88 EF 45 5E C1 19 64 D5 B3 C4 71 C1 1F 9B 05 68 D9 4B 4F B5 D3 4A A0 D6 69 A7 F3 E4 E2 83 FC EA 0A 60 3B D0 3E A5 62 D2 6D DB B1 F3 66 A3 24 E7 7D 5D DF 72 7C 33 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 67 D5 7B 95 4D EF 5F BB 89 35 BF D9 0A B8 +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 C0 30 00 00 67 C0 AA AA 03 00 40 96 00 02 10 09 15 CD 00 00 00 49 08 00 45 00 00 47 00 0B 00 00 80 01 1C 3A A1 2C EE 14 A1 2C EE 03 00 00 47 2E 06 00 6C 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 D8 A6 10 22 +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 00 45 00 00 47 00 0B 00 00 80 01 1C 3A A1 2C EE 14 A1 2C EE 03 00 00 47 2E 06 00 6C 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 +================================================================ +==== 802.11 packet (encrypted) ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 F0 38 00 01 1A 00 22 76 C2 12 82 07 BF 14 A2 E8 38 F4 F4 8A 96 E8 46 DF 7E B8 44 67 51 50 27 D1 EE 30 D4 97 06 C3 29 B9 B1 0A 7F 3B 20 73 A0 4F D9 44 0A 2C 61 C5 48 25 34 54 EC 8F CE D8 5C 77 3D 71 13 0D 07 52 44 75 18 F5 F4 5C ED 2D 5C 19 9F C8 01 26 80 8D 54 72 1F CF CE F0 BB 73 34 D2 36 3B 51 CD 56 C7 57 39 2D 83 D1 F8 EF 78 8C BD C4 50 82 35 9B B4 17 05 4E 4F A7 4E 78 5F 1C C8 CF 75 95 66 FB 20 21 B9 96 60 EC 47 94 64 C5 17 FD E2 06 E5 AF 2D 25 AA 18 76 80 E2 7F 00 7C CD 42 CA 68 58 4E 74 92 9F 20 2E 24 8F 27 CB 2C 6D 2F 68 C1 F8 85 53 2A C3 E7 EC E2 58 0B A4 E2 1B DA 34 34 30 48 FC 6C 5F 78 5C 39 7C B9 71 E2 E1 3A 7D 84 88 A9 7E FB 43 79 8D B3 FB C0 8A 65 6D C8 F9 F1 C0 B2 81 B3 C8 E8 97 7A 1A 25 9D 7C 8D 29 9F 88 E2 27 18 1B 60 59 A2 C1 2D EB 89 C6 39 CB A6 08 05 78 D7 8D A1 0F BD E7 B8 F0 40 E0 91 AC 17 1C 10 1C 01 78 68 0E 6D 14 E0 35 C4 00 59 B3 94 4E 6D 52 C6 AA C3 9A AA 24 A3 1B 7C 17 91 9E 97 64 94 FB BC 2E 68 1A E4 07 C3 D0 11 EB 6C A6 54 1B 4B 1D 08 5B 1F C1 DB F8 D6 8F A3 EE B4 E4 7F 64 D8 23 4B 24 DF CB 9B 68 BD 3C F9 AF AA B5 06 42 63 60 23 01 67 0A 2A 3B 4A A1 54 BE AE AD 60 5B BD 54 8E 70 37 2B F6 AD FB 49 99 0B 12 0F C1 B2 F9 2E C8 CB C4 1E E8 45 08 50 62 61 3A BE 7F 2F CE 49 BA 00 B9 A4 26 85 B3 4D F9 69 05 42 F5 76 4D 63 FD 1E BA 03 A8 7C 01 86 DE F6 EF D3 E9 5F 35 1F 77 48 82 8E DF B9 62 51 BC D0 05 DF 80 43 8F E0 C8 D0 4A 30 41 5C 27 28 A4 20 6B 9B 6B 30 AA 68 06 A8 E2 B3 56 4A 9C AA B7 E3 CD E0 94 F9 26 20 E7 6E F2 21 9A AE BD C8 B1 23 3B EA AC 68 F9 63 83 11 E6 4B 21 4A 05 3B 15 F0 AB A4 D6 94 46 65 E9 23 14 6E C4 2C E0 58 0F 54 C5 57 BF 66 10 AA 1B 83 F6 51 E4 E2 7D D5 55 C4 F3 F0 E3 57 27 36 FD C0 B9 36 F5 A9 38 0B CB 98 D1 70 38 4C C0 BF FB 17 E0 94 74 AE B5 F9 60 24 D7 4B BF 30 F1 AA BC C9 03 46 B9 C1 F0 1E 4A 4C 91 5D 9F C9 6F 94 6D FC 63 EC A9 3B 1B D5 62 6F C1 59 68 22 35 67 57 BF 9D C3 9D 44 60 4E EA 52 DE 38 FD EB 94 3C D5 6A 63 20 8E 90 C1 89 63 CF 47 5F 5A C0 A9 98 E0 6C 87 91 A8 88 38 56 03 36 31 82 92 0F 94 EC 95 A0 0F 50 F3 40 E0 A7 42 CA 4D B7 1B AE B4 E9 90 A6 47 BF 28 09 06 F0 C6 93 D0 A2 B9 26 8C 11 DB F8 8C 6A BD D6 A4 E2 61 5C 01 CB 72 1C 8A 58 FB 1D C3 F0 15 5B 3D 82 CE DB 34 00 7B 65 72 AB 04 D6 B8 90 CC 64 CC 28 66 D8 98 96 39 85 24 43 D1 98 2A 4F C2 FB CB 09 81 6F 9E 8D 53 D4 03 E6 BF 2A +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 01 1A 2A B0 CA 25 2B 0C B7 03 22 E4 CD BA B0 +==== 802.11 packet decrypted ==== +08 41 02 01 00 40 96 21 DC 83 00 40 96 28 8D DC 00 40 96 12 CE 40 F0 38 00 01 1A 00 AA AA 03 00 40 96 00 02 EF C0 38 BA 00 00 00 CA 08 00 45 00 02 DB 45 71 00 00 80 01 D4 3F A1 2C EE 03 A1 2C EE 14 08 00 93 74 06 00 6D 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D DD 5B 7F 71 +==== Original MSDU ==== +DA: 00 40 96 12 CE 40 +SA: 00 40 96 28 8D DC +Payload: 08 00 45 00 02 DB 45 71 00 00 80 01 D4 3F A1 2C EE 03 A1 2C EE 14 08 00 93 74 06 00 6D 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D +================================================================ +==== 802.11 packet (encrypted) ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 A0 31 00 00 68 C0 2C 57 A9 0D 2B FD 8B 58 08 91 FB A0 74 E7 72 32 CE 1C DD AF 3E 65 6A 89 B7 85 A2 48 AD A3 AD 93 90 5B 2E 58 20 55 36 6E 33 D1 EA 64 B4 73 AD EB 0B 8C 03 28 A6 04 7A 11 67 55 A9 E2 80 CF DF 83 21 95 D3 19 B8 05 18 1E 63 F3 4A 72 7B 8F 23 D2 75 6A C1 3D CE 4F 50 55 72 95 B2 E0 D9 63 F8 6B 65 01 1A BF 76 AD 51 FE 81 0A 52 E1 29 3B 6A F8 FC 8A 07 CE 2B 0D 91 4D 59 36 38 4C 31 04 8F 9C E0 CA E5 80 9E E0 37 4E A2 FE 3D 56 74 BB D7 98 17 0C 9C EC 83 6A 90 AC 0C 60 82 4B 3C 0A B0 6B F4 F6 18 88 E0 D5 74 A1 E4 5B EB DE E3 9A 40 62 69 58 A6 9E F3 69 A5 7A EF 27 2C 7A A4 A2 23 FD 0C DC 7B 16 8C 0D 5A CC 3B 34 EB C0 1C B8 9C 2D 38 1E DF ED 48 11 A2 83 6D A9 D0 B4 89 85 58 B8 EA 58 62 EF 0A 45 1E C8 43 59 63 56 6C EF 01 40 13 F2 A0 A3 0B A6 C2 25 F1 96 FD C3 2F 5F 2E 82 13 89 FD 4C E0 88 4A 8D BB 11 C8 48 0C 11 D4 A8 83 3E 77 59 26 44 72 66 B6 CD 6A D7 3B 37 F6 69 20 02 E8 F1 A6 A0 5A FA 70 66 B5 CA 55 2B 40 5A 0E FE 10 28 47 B5 A6 A1 3E 6B 23 1B 59 99 4E 0C E0 B0 0E A9 2C 5C 40 7E 56 F4 D3 2B 63 C2 4C F9 81 22 13 65 C9 F1 64 FC 98 F5 AC 5E 0B CE CA 31 22 2E 50 D8 6C 4C DF F4 82 9F FF 2E 3F 76 E5 33 88 85 E9 3F 9D 75 09 0A C9 54 2F 7B 0A A3 55 DC B1 24 5F DD C6 BC AC BA 3B 38 34 E0 57 A2 25 AA BD 4D 63 C4 65 93 60 9D 99 CC 28 D4 B2 E1 DF 00 7D 23 61 DA E6 6A EE 6B 7E 6C 06 BB FE 41 6F DC 22 F0 83 CA 34 EF 2B 05 DA FF A6 D5 C8 BC 6D 54 76 A2 29 92 FB 67 39 2A DF 81 5C 13 4D 7D 89 ED EF 27 F1 C7 97 07 6F 34 CE D3 AF 88 29 7D FE 08 EE D0 D5 87 51 92 17 28 8A 72 24 A6 75 68 AC C8 A0 B9 3A 38 BB DB D3 83 2C 95 24 6C 5E 31 28 B4 DA 08 38 66 25 E7 77 18 88 A7 53 07 F6 70 77 71 D0 95 0A EA 74 00 0F 13 D0 06 9C 40 68 0C C3 BF AA C7 DF 35 7C B7 05 4D 8B 20 9A 5B 4E 62 71 C3 34 49 56 BB 57 26 B3 3C A0 95 9B C0 32 62 62 5B 22 B9 ED 8C 93 2E A3 0B 24 E6 BF 80 A6 32 7F 1A 3A 8D A8 2A 75 F2 B4 19 3E 68 73 72 4B 20 3A C1 6D 6F B5 17 42 FF 1E B1 E2 29 E8 F1 B7 EE 84 CD 74 2E 3E 1B 81 69 C8 42 F2 C7 1C D9 64 0F 8D A4 2A 98 E9 CE 06 C2 20 A3 B7 7A 15 9C B9 4D 50 F4 25 42 D6 F2 9F 4A 3B 86 C0 47 75 CA EA EF A5 66 4B 5E E2 B4 71 53 5B E6 EE 29 0E E7 25 41 29 2B EE E9 51 96 BC F4 60 3C 4F 4B 16 0B CE 63 31 80 6F 16 9D 13 4D A3 80 D9 5D D3 C7 1A F5 8A DE B9 91 D1 E5 75 04 DE FB 7E ED 30 A8 C6 62 61 E3 BB 6D C6 4A E8 EC 06 6F EE D4 94 08 90 A7 47 55 F0 A2 +==== CK (basic CKIP key) ==== +19 59 8D F5 EF 19 59 8D F5 EF 19 59 8D F5 EF 19 +==== PK (permuted key) ==== +00 00 68 DA 0F 2D E1 15 FE EE BE 77 C9 BF 8E 28 +==== 802.11 packet decrypted ==== +08 42 D5 00 00 40 96 28 8D DC 00 40 96 21 DC 83 00 40 96 12 CE 40 A0 31 00 00 68 C0 AA AA 03 00 40 96 00 02 29 BE FD C7 00 00 00 4B 08 00 45 00 02 DB 00 0C 00 00 80 01 19 A5 A1 2C EE 14 A1 2C EE 03 00 00 9B 74 06 00 6D 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D DE C1 6F 1A +==== Original MSDU ==== +DA: 00 40 96 28 8D DC +SA: 00 40 96 12 CE 40 +Payload: 08 00 45 00 02 DB 00 0C 00 00 80 01 19 A5 A1 2C EE 14 A1 2C EE 03 00 00 9B 74 06 00 6D 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D +================================================================ +#endif /* BCMCCX */ diff --git a/release/src-rt/bcmcrypto/des.c b/release/src-rt/bcmcrypto/des.c new file mode 100755 index 0000000000..f59233b4c8 --- /dev/null +++ b/release/src-rt/bcmcrypto/des.c @@ -0,0 +1,655 @@ +/* + * DES functions + * Copied from des-ka9q-1.0-portable, a public domain DES implementation, + * and diddled with only enough to compile without warnings and link + * with our driver. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: des.c,v 1.12 2009-10-21 23:12:36 Exp $ + */ + +/* Portable C code to create DES key schedules from user-provided keys + * This doesn't have to be fast unless you're cracking keys or UNIX + * passwords + */ + +#include +#ifdef BCMDRIVER +#include +#else +#include /* for size_t */ +#if defined(__GNUC__) +#include +#else +#include +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif /* __GNUC__ */ +#endif /* BCMDRIVER */ +#include + +const unsigned long BCMROMDATA(Spbox)[8][64] = { + { + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 + }, + { + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 + }, + { + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 + }, + { + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 + }, + { + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 + }, + { + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 + }, + { + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 + }, + { + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 + } +}; + + +/* Key schedule-related tables from FIPS-46 */ + +/* permuted choice table (key) */ +static const unsigned char pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 01, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 07, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const unsigned char totrot[] = { + 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 +}; + +/* permuted choice key (table) */ +static const unsigned char pc2[] = { + 14, 17, 11, 24, 1, 5, + 03, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + + +/* int Asmversion = 0; */ +#define Asmversion 0 + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + + +/* Generate key schedule for encryption or decryption + * depending on the value of "decrypt" + */ +void +BCMROMFN(deskey)(DES_KS k, /* Key schedule array */ + unsigned char *key, /* 64 bits (will use only 56) */ + int decrypt) /* 0 = encrypt, 1 = decrypt */ +{ + unsigned char pc1m[56]; /* place to modify pc1 into */ + unsigned char pcr[56]; /* place to rotate pc1 into */ + register int i, j, l; + int m; + unsigned char ks[8]; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + bzero(ks, sizeof(ks)); /* Clear key schedule */ + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l = j + totrot[decrypt ? 15 - i : i]) < + (j < 28 ? 28 : 56) ? l : l - 28]; + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++) { /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j] - 1]) { + /* mask it in if it's there */ + l = j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to packed odd/even interleaved form */ + k[i][0] = (((long)ks[0] << 24) | + ((long)ks[2] << 16) | + ((long)ks[4] << 8) | + ((long)ks[6])); + k[i][1] = (((long)ks[1] << 24) | + ((long)ks[3] << 16) | + ((long)ks[5] << 8) | + ((long)ks[7])); + if (Asmversion) { + /* The assembler versions pre-shift each subkey 2 bits + * so the Spbox indexes are already computed + */ + k[i][0] <<= 2; + k[i][1] <<= 2; + } + } +} + +/* Portable C version of des() function */ + +/* Tables defined in the Data Encryption Standard documents + * Three of these tables, the initial permutation, the final + * permutation and the expansion operator, are regular enough that + * for speed, we hard-code them. They're here for reference only. + * Also, the S and P boxes are used by a separate program, gensp.c, + * to build the combined SP box, Spbox[]. They're also here just + * for reference. + */ +#ifdef notdef +/* initial permutation IP */ +static unsigned char ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static unsigned char fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; +/* expansion operation matrix */ +static unsigned char ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +/* The (in)famous S-boxes */ +static unsigned char sbox[8][64] = { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 00, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 04, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 03, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 00, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 01, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + + /* S4 */ + 07, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 03, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + + /* S5 */ + 02, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 04, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + + /* S7 */ + 04, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 01, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 06, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 01, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 07, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 02, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +static unsigned char p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 01, 15, 23, 26, + 05, 18, 31, 10, + 02, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; +#endif /* notdef */ + +/* Combined SP lookup table, linked in + * For best results, ensure that this is aligned on a 32-bit boundary; + * Borland C++ 3.1 doesn't guarantee this! + */ + +/* Primitive function F. + * Input is r, subkey array in keys, output is XORed into l. + * Each round consumes eight 6-bit subkeys, one for + * each of the 8 S-boxes, 2 longs for each round. + * Each long contains four 6-bit subkeys, each taking up a byte. + * The first long contains, from high to low end, the subkeys for + * S-boxes 1, 3, 5 & 7; the second contains the subkeys for S-boxes + * 2, 4, 6 & 8 (using the origin-1 S-box numbering in the standard, + * not the origin-0 numbering used elsewhere in this code) + * See comments elsewhere about the pre-rotated values of r and Spbox. + */ +#define F(l, r, key) { \ + work = ((r >> 4) | (r << 28)) ^ key[0]; \ + l ^= Spbox[6][work & 0x3f]; \ + l ^= Spbox[4][(work >> 8) & 0x3f]; \ + l ^= Spbox[2][(work >> 16) & 0x3f]; \ + l ^= Spbox[0][(work >> 24) & 0x3f]; \ + work = r ^ key[1]; \ + l ^= Spbox[7][work & 0x3f]; \ + l ^= Spbox[5][(work >> 8) & 0x3f]; \ + l ^= Spbox[3][(work >> 16) & 0x3f]; \ + l ^= Spbox[1][(work >> 24) & 0x3f]; \ +} +/* Encrypt or decrypt a block of data in ECB mode */ +void +BCMROMFN(des)(unsigned long ks[16][2], /* Key schedule */ + unsigned char block[8]) /* Data block */ +{ + unsigned long left, right, work; +#if defined(BCMROMBUILD) + int round; +#endif + + /* Read input block and place in left/right in big-endian order */ + left = (((unsigned long)block[0] << 24) | + ((unsigned long)block[1] << 16) | + ((unsigned long)block[2] << 8) | + (unsigned long)block[3]); + right = (((unsigned long)block[4] << 24) | + ((unsigned long)block[5] << 16) | + ((unsigned long)block[6] << 8) | + (unsigned long)block[7]); + + /* Hoey's clever initial permutation algorithm, from Outerbridge + * (see Schneier p 478) + * + * The convention here is the same as Outerbridge: rotate each + * register left by 1 bit, i.e., so that "left" contains permuted + * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 + * (using origin-1 numbering as in the FIPS). This allows us to avoid + * one of the two rotates that would otherwise be required in each of + * the 16 rounds. + */ + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = (right << 1) | (right >> 31); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + /* Now do the 16 rounds. + * Fully unrolling generates 4x larger ARM code for this function + */ +#if defined(BCMROMBUILD) + for (round = 0; round < 16; round += 2) { + F(left, right, ks[round + 0]); + F(right, left, ks[round + 1]); + } +#else /* !BCMROMBUILD */ + F(left, right, ks[0]); + F(right, left, ks[1]); + F(left, right, ks[2]); + F(right, left, ks[3]); + F(left, right, ks[4]); + F(right, left, ks[5]); + F(left, right, ks[6]); + F(right, left, ks[7]); + F(left, right, ks[8]); + F(right, left, ks[9]); + F(left, right, ks[10]); + F(right, left, ks[11]); + F(left, right, ks[12]); + F(right, left, ks[13]); + F(left, right, ks[14]); + F(right, left, ks[15]); +#endif /* !BCMROMBUILD */ + + /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ + right = (right << 31) | (right >> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left >> 1) | (left << 31); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; + + /* Put the block back into the user's buffer with final swap */ + block[0] = (unsigned char)(right >> 24); + block[1] = (unsigned char)(right >> 16); + block[2] = (unsigned char)(right >> 8); + block[3] = (unsigned char)right; + block[4] = (unsigned char)(left >> 24); + block[5] = (unsigned char)(left >> 16); + block[6] = (unsigned char)(left >> 8); + block[7] = (unsigned char)left; +} + +#ifdef DES_TEST_STANDALONE +#include +#include +#include + +static unsigned long +randlong(void) +{ + static unsigned long r = 0; + if (r == 0) + r = getpid() * time(0) * 153846157; + r = (r + 7180351) * 74449801; + return r; +} + +static void +dumpit(int sample, unsigned long ks[16][2], unsigned char in[8], unsigned char out[8]) +{ + int i; + + printf("unsigned long sample%d_ks[16][2] = {\n", sample); + for (i = 0; i < 16; i++) + printf("\t{ 0x%08lx, 0x%08lx },\n", ks[i][0], ks[i][1]); + printf("};\n\n"); + printf("unsigned char sample%d_in[8] = {\n\t", sample); + for (i = 0; i < 8; i++) + printf("%s0x%02x,", i > 0 ? " " : "", in[i]); + printf("\n};\n\n"); + printf("unsigned char sample%d_out[8] = {\n\t", sample); + for (i = 0; i < 8; i++) + printf("%s0x%02x,", i > 0 ? " " : "", out[i]); + printf("\n};\n\n"); +} + +void +gensample(int sample) +{ + unsigned long ks[16][2]; + unsigned char in[8], out[8]; + int i, j; + + for (i = 0; i < 16; i++) + for (j = 0; j < 2; j++) + ks[i][j] = randlong(); + + for (i = 0; i < 8; i++) + in[i] = out[i] = randlong() & 0xff; + + des(ks, out); + + dumpit(sample, ks, in, out); +} + +int +checksample(unsigned long ks[16][2], unsigned char in[8], unsigned char expected_out[8]) +{ + des(ks, in); + return (bcmp(in, expected_out, 8) == 0); +} + +unsigned long sample1_ks[16][2] = { + { 0xe75fea2c, 0xb035c443 }, + { 0x7245bf92, 0xab5529d9 }, + { 0xfde3ded8, 0x03f1b84f }, + { 0x6af77dfe, 0xd6ef55a5 }, + { 0x7b28b304, 0x5f83c7db }, + { 0x1f9073ea, 0x8eecb4f1 }, + { 0xcb1e96b0, 0x5705a2e7 }, + { 0x1edfd156, 0xadbdf7bd }, + { 0x2623b9dc, 0x2f6ef973 }, + { 0x3882c642, 0x2611ce09 }, + { 0x77c44c88, 0x9b557b7f }, + { 0xbfa482ae, 0xfb94e7d5 }, + { 0xbd7a7eb4, 0xafacd90b }, + { 0xc5be369a, 0xf3b1f521 }, + { 0xdd6e8060, 0x1086c217 }, + { 0x4d571206, 0xfe51a5ed }, +}; + +unsigned char sample1_in[8] = { + 0x8c, 0xa3, 0xf2, 0x39, 0x38, 0xaf, 0x5e, 0x05, +}; + +unsigned char sample1_out[8] = { + 0x0e, 0x38, 0x62, 0x0a, 0x72, 0x93, 0xc8, 0x25, +}; + +unsigned long sample2_ks[16][2] = { + { 0xf130845c, 0x97a6d7f3 }, + { 0xfe0458c2, 0x7520b489 }, + { 0xcb712708, 0x0165e9ff }, + { 0xe7bb252e, 0xcb995e55 }, + { 0xf5416934, 0x75dfd78b }, + { 0xc803e91a, 0x1415fba1 }, + { 0x37097ae0, 0x6d665097 }, + { 0xf7a5d486, 0x26bf3c6d }, + { 0xb89f8c0c, 0xbc290523 }, + { 0x93361772, 0x0efbd0b9 }, + { 0xc807ccb8, 0x2ef5a52f }, + { 0x9dd7e1de, 0xe4306885 }, + { 0x18346ce4, 0x5ff7e0bb }, + { 0x1bfc63ca, 0x5a7fb3d1 }, + { 0x77c59c90, 0xc37967c7 }, + { 0x2622cd36, 0x0b8a629d }, +}; + +unsigned char sample2_in[8] = { + 0xbc, 0x53, 0x22, 0xe9, 0x68, 0x5f, 0x8e, 0xb5, +}; + +unsigned char sample2_out[8] = { + 0x76, 0xb9, 0xdf, 0xb8, 0x2a, 0x5b, 0x50, 0x48, +}; + +int +main(int argc, char **argv) +{ + + if (!checksample(sample1_ks, sample1_in, sample1_out)) + printf("sample1 bad\n"); + else if (!checksample(sample2_ks, sample2_in, sample2_out)) + printf("sample2 bad\n"); + else + printf("pass\n"); + + return 0; +} + +#endif /* DES_TEST_STANDALONE */ diff --git a/release/src-rt/bcmcrypto/dh.c b/release/src-rt/bcmcrypto/dh.c new file mode 100755 index 0000000000..7e3b673d47 --- /dev/null +++ b/release/src-rt/bcmcrypto/dh.c @@ -0,0 +1,617 @@ +/* + * dh.c: Diffie Hellman implementation. + * + * Code copied from openssl distribution and + * Modified just enough so that compiles and runs standalone + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: dh.c,v 1.9.108.1 2010-08-13 18:00:15 Exp $ + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +/* #include */ + +#include + +#define OPENSSL_malloc malloc +#define OPENSSL_free free + + +static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + +#ifdef BCMDH_TEST + +#include + +static int bn_print(const BIGNUM *a); +static void cb(int p, int n, void *arg); + +unsigned char data192[] = { + 0xD4, 0xA0, 0xBA, 0x02, 0x50, 0xB6, 0xFD, 0x2E, + 0xC6, 0x26, 0xE7, 0xEF, 0xD6, 0x37, 0xDF, 0x76, + 0xC7, 0x16, 0xE2, 0x2D, 0x09, 0x44, 0xB8, 0x8B +}; + +unsigned char data512[] = { + 0xDA, 0x58, 0x3C, 0x16, 0xD9, 0x85, 0x22, 0x89, + 0xD0, 0xE4, 0xAF, 0x75, 0x6F, 0x4C, 0xCA, 0x92, + 0xDD, 0x4B, 0xE5, 0x33, 0xB8, 0x04, 0xFB, 0x0F, + 0xED, 0x94, 0xEF, 0x9C, 0x8A, 0x44, 0x03, 0xED, + 0x57, 0x46, 0x50, 0xD3, 0x69, 0x99, 0xDB, 0x29, + 0xD7, 0x76, 0x27, 0x6B, 0xA2, 0xD3, 0xD4, 0x12, + 0xE2, 0x18, 0xF4, 0xDD, 0x1E, 0x08, 0x4C, 0xF6, + 0xD8, 0x00, 0x3E, 0x7C, 0x47, 0x74, 0xE8, 0x33 +}; + +unsigned char data1024[] = { + 0x97, 0xF6, 0x42, 0x61, 0xCA, 0xB5, 0x05, 0xDD, + 0x28, 0x28, 0xE1, 0x3F, 0x1D, 0x68, 0xB6, 0xD3, + 0xDB, 0xD0, 0xF3, 0x13, 0x04, 0x7F, 0x40, 0xE8, + 0x56, 0xDA, 0x58, 0xCB, 0x13, 0xB8, 0xA1, 0xBF, + 0x2B, 0x78, 0x3A, 0x4C, 0x6D, 0x59, 0xD5, 0xF9, + 0x2A, 0xFC, 0x6C, 0xFF, 0x3D, 0x69, 0x3F, 0x78, + 0xB2, 0x3D, 0x4F, 0x31, 0x60, 0xA9, 0x50, 0x2E, + 0x3E, 0xFA, 0xF7, 0xAB, 0x5E, 0x1A, 0xD5, 0xA6, + 0x5E, 0x55, 0x43, 0x13, 0x82, 0x8D, 0xA8, 0x3B, + 0x9F, 0xF2, 0xD9, 0x41, 0xDE, 0xE9, 0x56, 0x89, + 0xFA, 0xDA, 0xEA, 0x09, 0x36, 0xAD, 0xDF, 0x19, + 0x71, 0xFE, 0x63, 0x5B, 0x20, 0xAF, 0x47, 0x03, + 0x64, 0x60, 0x3C, 0x2D, 0xE0, 0x59, 0xF5, 0x4B, + 0x65, 0x0A, 0xD8, 0xFA, 0x0C, 0xF7, 0x01, 0x21, + 0xC7, 0x47, 0x99, 0xD7, 0x58, 0x71, 0x32, 0xBE, + 0x9B, 0x99, 0x9B, 0xB9, 0xB7, 0x87, 0xE8, 0xAB +}; + +/* uncomment this and write a matching function when testing on another OS */ +#ifndef WIN32 +#define BCMDH_TEST_LINUX +#endif + +#ifdef BCMDH_TEST_LINUX + +#define dbg(fmt, arg...) printf(fmt, ##arg) + +#endif /* BCMDH_TEST_LINUX */ + + +int +main(int argc, char *argv[]) +{ + DH *a; + DH *b = NULL; + unsigned char *abuf = NULL, *bbuf = NULL; + unsigned char *apubbuf = NULL, *bpubbuf = NULL; + int i, alen, blen, apublen, bpublen, aout, bout, ret = 1, size = 0; + char opt; + + while ((opt = getopt(argc, argv, "s:")) != EOF) { + switch (opt) { + case 's': + size = (int)strtoul(optarg, NULL, 0); + break; + default: + dbg("invalid option"); + return ret; + } + } + +#ifdef BCMDH_TEST_LINUX + { + extern void linux_random(uint8 *rand, int len); + BN_register_RAND(linux_random); + } +#endif + + if (size == 192) { + a = DH_init(data192, sizeof(data192), 3); + } else if (size == 512) { + a = DH_init(data512, sizeof(data512), 2); + } else if (size == 1024) { + a = DH_init(data1024, sizeof(data1024), 2); + } else { + a = DH_generate_parameters(NULL, 64, DH_GENERATOR_5, cb, NULL); + if (a == NULL) goto err; + } + + if (!DH_check(a, &i)) goto err; + if (i & DH_CHECK_P_NOT_PRIME) + dbg("p value is not prime\n"); + if (i & DH_CHECK_P_NOT_SAFE_PRIME) + dbg("p value is not a safe prime\n"); + if (i & DH_UNABLE_TO_CHECK_GENERATOR) + dbg("unable to check the generator value\n"); + if (i & DH_NOT_SUITABLE_GENERATOR) + dbg("the g value is not a generator\n"); + + dbg("\np ="); + bn_print(a->p); + dbg("\ng ="); + bn_print(a->g); + dbg("\n"); + + b = DH_new(); + if (b == NULL) goto err; + + b->p = BN_dup(a->p); + b->g = BN_dup(a->g); + if ((b->p == NULL) || (b->g == NULL)) goto err; + + apubbuf = (unsigned char *)OPENSSL_malloc(DH_size(a)); + /* dbg("%s\n", file2str("/proc/uptime")); */ + if (!(apublen = DH_generate_key(apubbuf, a))) goto err; + /* dbg("%s\n", file2str("/proc/uptime")); */ + dbg("pri 1="); + bn_print(a->priv_key); + dbg("\npub 1="); + for (i = 0; i < apublen; i++) dbg("%02X", apubbuf[i]); + dbg("\n"); + + bpubbuf = (unsigned char *)OPENSSL_malloc(DH_size(b)); + if (!(bpublen = DH_generate_key(bpubbuf, b))) goto err; + dbg("pri 2="); + bn_print(b->priv_key); + dbg("\npub 2="); + for (i = 0; i < bpublen; i++) dbg("%02X", bpubbuf[i]); + dbg("\n"); + + alen = DH_size(a); + abuf = (unsigned char *)OPENSSL_malloc(alen); + /* dbg("%s\n", file2str("/proc/uptime")); */ + aout = DH_compute_key(abuf, bpubbuf, bpublen, a); + /* dbg("%s\n", file2str("/proc/uptime")); */ + + dbg("key1 ="); + for (i = 0; i < aout; i++) dbg("%02X", abuf[i]); + dbg("\n"); + + blen = DH_size(b); + bbuf = (unsigned char *)OPENSSL_malloc(blen); + bout = DH_compute_key(bbuf, apubbuf, apublen, b); + + dbg("key2 ="); + for (i = 0; i < bout; i++) dbg("%02X", abuf[i]); + dbg("\n"); + + if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) + ret = 1; + else + ret = 0; +err: + if (abuf != NULL) OPENSSL_free(abuf); + if (bbuf != NULL) OPENSSL_free(bbuf); + if (b != NULL) DH_free(b); + if (a != NULL) DH_free(a); + fprintf(stderr, "%s: %s\n", *argv, ret?"FAILED":"PASSED"); + return (ret); +} + +static void +cb(int p, int n, void *arg) +{ + if (p == 0) dbg("."); + if (p == 1) dbg("+"); + if (p == 2) dbg("*"); + if (p == 3) dbg("\n"); +} + +static const char *Hex = "0123456789ABCDEF"; + +static int +bn_print(const BIGNUM *a) +{ + int i, j, v, z = 0; + int ret = 0; + + if ((a->neg) && (dbg("-") != 1)) goto end; + if ((a->top == 0) && (dbg("0") != 1)) goto end; + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 4; j >= 0; j -= 4) { + /* strip leading zeros */ + v = ((int)(a->d[i] >> (long)j)) & 0x0f; + if (z || (v != 0)) { + dbg("%c", Hex[v]); + z = 1; + } + } + } + ret = 1; +end: + return (ret); +} + +int DH_size(const DH *dh) +{ + return (BN_num_bytes(dh->p)); +} + +/* We generate DH parameters as follows + * find a prime q which is prime_len/2 bits long. + * p=(2*q)+1 or (p-1)/2 = q + * For this case, g is a generator if + * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. + * Since the factors of p-1 are q and 2, we just need to check + * g^2 mod p != 1 and g^q mod p != 1. + * + * Having said all that, + * there is another special case method for the generators 2, 3 and 5. + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 <<<<< does not work for safe primes. + * for 5, p mod 10 == 3 or 7 + * + * Thanks to Phil Karn for the pointers about the + * special generators and for answering some of my questions. + * + * I've implemented the second simple method :-). + * Since DH should be using a safe prime (both p and q are prime), + * this generator function can take a very very long time to run. + */ +/* Actually there is no reason to insist that 'generator' be a generator. + * It's just as OK (and in some sense better) to use a generator of the + * order-q subgroup. + */ +DH * +DH_generate_parameters(DH* dh, int prime_len, int generator, + void (*callback)(int, int, void *), void *cb_arg) +{ + BIGNUM *p = NULL, *t1, *t2; + DH *ret = NULL; + int g, ok = -1; + BN_CTX *ctx = NULL; + + ret = dh ? dh : DH_new(); + if (ret == NULL) goto err; + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) goto err; + + if (generator <= 1) { + goto err; + } + if (generator == DH_GENERATOR_2) { + if (!BN_set_word(t1, 24)) goto err; + if (!BN_set_word(t2, 11)) goto err; + g = 2; + } + + else if (generator == DH_GENERATOR_5) { + if (!BN_set_word(t1, 10)) goto err; + if (!BN_set_word(t2, 3)) goto err; + /* BN_set_word(t3, 7); just have to miss + * out on these ones :-( + */ + g = 5; + } else { + /* in the general case, don't worry if 'generator' is a + * generator or not: since we are using safe primes, + * it will generate either an order-q or an order-2q group, + * which both is OK + */ + if (!BN_set_word(t1, 2)) goto err; + if (!BN_set_word(t2, 1)) goto err; + g = generator; + } + + p = BN_generate_prime(NULL, prime_len, 1, t1, t2, callback, cb_arg); + if (p == NULL) goto err; + if (callback != NULL) callback(3, 0, cb_arg); + ret->p = p; + ret->g = BN_new(); + if (!BN_set_word(ret->g, g)) goto err; + ok = 1; +err: + if (ok == -1) { + ok = 0; + } + + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (!ok && (ret != NULL)) { + DH_free(ret); + ret = NULL; + } + return (ret); +} + +/* Check that p is a safe prime and + * if g is 2, 3 or 5, check that is is a suitable generator + * where + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 + * for 5, p mod 10 == 3 or 7 + * should hold. + */ + +int +DH_check(const DH *dh, int *ret) +{ + int ok = 0; + BN_CTX *ctx = NULL; + BN_ULONG l; + BIGNUM *q = NULL; + + *ret = 0; + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; + q = BN_new(); + if (q == NULL) goto err; + + if (BN_is_word(dh->g, DH_GENERATOR_2)) { + l = BN_mod_word(dh->p, 24); + if (l != 11) *ret |= DH_NOT_SUITABLE_GENERATOR; + } + + else if (BN_is_word(dh->g, DH_GENERATOR_5)) { + l = BN_mod_word(dh->p, 10); + if ((l != 3) && (l != 7)) + *ret |= DH_NOT_SUITABLE_GENERATOR; + } else + *ret |= DH_UNABLE_TO_CHECK_GENERATOR; + + if (!BN_is_prime(dh->p, BN_prime_checks, NULL, ctx, NULL)) + *ret |= DH_CHECK_P_NOT_PRIME; + else { + if (!BN_rshift1(q, dh->p)) goto err; + if (!BN_is_prime(q, BN_prime_checks, NULL, ctx, NULL)) + *ret |= DH_CHECK_P_NOT_SAFE_PRIME; + } + ok = 1; +err: + if (ctx != NULL) BN_CTX_free(ctx); + if (q != NULL) BN_free(q); + return (ok); +} + +#endif /* BCMDH_TEST */ + +DH * +DH_new(void) +{ + DH *ret; + + ret = (DH *)OPENSSL_malloc(sizeof(DH)); + if (ret == NULL) { + return (NULL); + } + + ret->p = NULL; + ret->g = NULL; + ret->length = 0; + ret->pub_key = NULL; + ret->priv_key = NULL; + ret->q = NULL; + ret->j = NULL; + ret->seed = NULL; + ret->seedlen = 0; + ret->counter = NULL; + ret->method_mont_p = NULL; + ret->flags = DH_FLAG_CACHE_MONT_P; + return (ret); +} + +void +DH_free(DH *r) +{ + if (r == NULL) return; + if (r->p != NULL) BN_clear_free(r->p); + if (r->g != NULL) BN_clear_free(r->g); + if (r->q != NULL) BN_clear_free(r->q); + if (r->j != NULL) BN_clear_free(r->j); + if (r->seed) OPENSSL_free(r->seed); + if (r->counter != NULL) BN_clear_free(r->counter); + if (r->pub_key != NULL) BN_clear_free(r->pub_key); + if (r->priv_key != NULL) BN_clear_free(r->priv_key); + if (r->method_mont_p) + BN_MONT_CTX_free((BN_MONT_CTX *)r->method_mont_p); + OPENSSL_free(r); +} + +int +DH_generate_key(unsigned char *pubbuf, DH *dh) +{ + int ret = 0; + unsigned l; + BN_CTX *ctx = NULL; + BN_MONT_CTX *mont; + BIGNUM *pub_key = NULL, *priv_key = NULL; + + + if (dh->pub_key != NULL) { + if (pubbuf) + return BN_bn2bin(dh->pub_key, pubbuf); + else + return BN_num_bytes(dh->pub_key); + } + /* first time in here */ + priv_key = BN_new(); + if (priv_key == NULL) goto err; + + pub_key = BN_new(); + if (pub_key == NULL) goto err; + + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; + + if (dh->flags & DH_FLAG_CACHE_MONT_P) { + if ((dh->method_mont_p = BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p, + dh->p, ctx)) + goto err; + } + + mont = (BN_MONT_CTX *)dh->method_mont_p; + + l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */ + if (!BN_rand(priv_key, l, 0, 0)) + goto err; + if (!dh_bn_mod_exp(dh, pub_key, dh->g, priv_key, dh->p, ctx, mont)) + goto err; + + dh->pub_key = pub_key; + dh->priv_key = priv_key; + if (pubbuf) + ret = BN_bn2bin(pub_key, pubbuf); + else + ret = BN_num_bytes(dh->pub_key); +err: + if ((pub_key != NULL) && (dh->pub_key == NULL)) + BN_free(pub_key); + if ((priv_key != NULL) && (dh->priv_key == NULL)) + BN_free(priv_key); + if (ctx) + BN_CTX_free(ctx); + return (ret); +} + + +int +DH_compute_key_bn(unsigned char *key, BIGNUM *peer_key, DH *dh) +{ + BN_CTX *ctx; + BN_MONT_CTX *mont; + BIGNUM *tmp; + int ret = -1; + + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + + if (dh->priv_key == NULL) { + goto err; + } + if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P)) { + if ((dh->method_mont_p = BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p, + dh->p, ctx)) + goto err; + } + + mont = (BN_MONT_CTX *)dh->method_mont_p; + if (!dh_bn_mod_exp(dh, tmp, peer_key, dh->priv_key, dh->p, ctx, mont)) { + goto err; + } + + ret = BN_bn2bin(tmp, key); +err: + if (peer_key) + BN_clear_free(peer_key); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return (ret); +} + + +int +DH_compute_key(unsigned char *key, unsigned char *pubbuf, int buflen, DH *dh) +{ + BIGNUM *peer_key = NULL; + + peer_key = BN_bin2bn(pubbuf, buflen, NULL); + return DH_compute_key_bn(key, peer_key, dh); +} + +DH * +DH_init(unsigned char *pbuf, int plen, int g) +{ + DH *dh; + + dh = DH_new(); + dh->p = BN_bin2bn(pbuf, plen, NULL); + dh->g = BN_new(); + BN_set_word(dh->g, g); + return dh; +} + +static int +dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) +{ + if (a->top == 1) { + BN_ULONG A = a->d[0]; + return BN_mod_exp_mont_word(r, A, p, m, ctx, m_ctx); + } else + return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); +} diff --git a/release/src-rt/bcmcrypto/prebuilt/.dummy b/release/src-rt/bcmcrypto/examccx.h old mode 100644 new mode 100755 similarity index 100% copy from release/src-rt/bcmcrypto/prebuilt/.dummy copy to release/src-rt/bcmcrypto/examccx.h diff --git a/release/src-rt/bcmcrypto/prebuilt/.dummy b/release/src-rt/bcmcrypto/examppkt.h old mode 100644 new mode 100755 similarity index 100% rename from release/src-rt/bcmcrypto/prebuilt/.dummy rename to release/src-rt/bcmcrypto/examppkt.h diff --git a/release/src-rt/bcmcrypto/hmac.c b/release/src-rt/bcmcrypto/hmac.c new file mode 100755 index 0000000000..fb5eb691d1 --- /dev/null +++ b/release/src-rt/bcmcrypto/hmac.c @@ -0,0 +1,136 @@ +/* + * Function: hmac_md5 + * From rfc2104.txt + * + * $Id: hmac.c,v 1.16 2009-04-13 16:25:16 Exp $ + */ + +/* + * Copyright (C) The Internet Society (2001). All Rights Reserved. + * + * This document and translations of it may be copied and furnished to + * others, and derivative works that comment on or otherwise explain it + * or assist in its implementation may be prepared, copied, published + * and distributed, in whole or in part, without restriction of any + * kind, provided that the above copyright notice and this paragraph are + * included on all such copies and derivative works. However, this + * document itself may not be modified in any way, such as by removing + * the copyright notice or references to the Internet Society or other + * Internet organizations, except as needed for the purpose of + * developing Internet standards in which case the procedures for + * copyrights defined in the Internet Standards process must be + * followed, or as required to translate it into languages other than + * English. + * + * The limited permissions granted above are perpetual and will not be + * revoked by the Internet Society or its successors or assigns. + * + * This document and the information contained herein is provided on an + * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: hmac.c,v 1.16 2009-04-13 16:25:16 Exp $ + */ + + +#include + +#ifdef BCMDRIVER +#if !defined(BCMSUP_PSK) +#error "BCMSUP_PSK or BCMCCX must be defined to compile hmac.c for driver!" +#endif +#include +#else +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, int len); +extern void bzero(void *b, int len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif +#endif /* BCMDRIVER */ + + +extern void BCMROMFN(hmac_md5)(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest); + +/* text pointer to data stream */ +/* text_len length of data stream */ +/* key pointer to authentication key */ +/* key_len length of authentication key */ +/* digest caller digest to be filled in */ +void +BCMROMFN(hmac_md5)(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest) +{ + MD5_CTX context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + bzero(k_ipad, sizeof(k_ipad)); + bzero(k_opad, sizeof(k_opad)); + bcopy(key, k_ipad, key_len); + bcopy(key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + MD5Init(&context); /* init context for 1st pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ +} diff --git a/release/src-rt/bcmcrypto/hmac_sha256.c b/release/src-rt/bcmcrypto/hmac_sha256.c new file mode 100755 index 0000000000..c8409c9ced --- /dev/null +++ b/release/src-rt/bcmcrypto/hmac_sha256.c @@ -0,0 +1,236 @@ +/* crypto/hmac/hmac.c + * Code copied from openssl distribution and + * Modified just enough so that compiles and runs standalone + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: hmac_sha256.c,v 1.5.218.2 2010-06-08 01:29:21 Exp $ + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#include +#ifdef BCMDRIVER +#include +#else +#include /* for size_t */ +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, size_t len); +extern int bcmp(const void *b1, const void *b2, size_t len); +extern void bzero(void *b, size_t len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif /* defined(__GNUC__) */ + +#include +#include +#include +#endif /* BCMDRIVER */ + +#include "bcmcrypto/sha256.h" +#include "bcmcrypto/hmac_sha256.h" + +#include "bcmutils.h" + +void +hmac_sha256(const void *key, int key_len, + const unsigned char *text, size_t text_len, unsigned char *digest, + unsigned int *digest_len) + +{ + SHA256_CTX ctx; + + int i; + unsigned char sha_key[SHA256_CBLOCK]; + unsigned char k_ipad[SHA256_CBLOCK]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[SHA256_CBLOCK]; /* outer padding - + * key XORd with opad + */ + /* set the key */ + /* block size smaller than key size : hash down */ + if (SHA256_CBLOCK < key_len) + { + SHA256_Init(&ctx); + SHA256_Update(&ctx, key, key_len); + SHA256_Final(sha_key, &ctx); + key = sha_key; + key_len = SHA256_DIGEST_LENGTH; + } + + /* + * the HMAC_SHA256 transform looks like: + * + * SHA256(K XOR opad, SHA256(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + /* compute inner and outer pads from key */ + bzero(k_ipad, sizeof(k_ipad)); + bzero(k_opad, sizeof(k_opad)); + bcopy(key, k_ipad, key_len); + bcopy(key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + + /* + * perform inner SHA256 + */ + SHA256_Init(&ctx); /* init context for 1st pass */ + SHA256_Update(&ctx, k_ipad, SHA256_CBLOCK); /* start with inner pad */ + SHA256_Update(&ctx, text, text_len); /* then text of datagram */ + SHA256_Final(digest, &ctx); /* finish up 1st pass */ + /* + * perform outer SHA256 + */ + SHA256_Init(&ctx); /* init context for 2nd pass */ + SHA256_Update(&ctx, k_opad, SHA256_CBLOCK); /* start with outer pad */ + SHA256_Update(&ctx, digest, SHA256_DIGEST_LENGTH); /* then results of 1st hash */ + SHA256_Final(digest, &ctx); /* finish up 2nd pass */ + + if (digest_len) + *digest_len = SHA256_DIGEST_LENGTH; +} + +void hmac_sha256_n(const void *key, int key_len, + const unsigned char *text, size_t text_len, unsigned char *digest, + unsigned int digest_len) +{ + uchar data[128]; + uchar digest_tmp[SHA256_DIGEST_LENGTH]; + int data_len = 2; + unsigned int i; + uint16 digest_bitlen = (digest_len*8); + + *(uint16 *)data = 0; + + + bcopy(text, &data[data_len], text_len); + data_len += text_len; + bcopy((uchar *)&digest_bitlen, &data[data_len], sizeof(uint16)); + data_len += sizeof(uint16); + for (i = 0; i < (digest_len + SHA256_DIGEST_LENGTH - 1) / SHA256_DIGEST_LENGTH; i++) { + *(uint16 *)data = (uint16) i + 1; + hmac_sha256(key, key_len, data, data_len, digest_tmp, NULL); + bcopy(digest_tmp, &digest[(i*SHA256_DIGEST_LENGTH)], SHA256_DIGEST_LENGTH); + } +} + +void +sha256(const unsigned char *text, size_t text_len, unsigned char *digest, + unsigned int digest_len) +{ + SHA256_CTX ctx; + + SHA256_Init(&ctx); /* init context for 1st pass */ + SHA256_Update(&ctx, text, text_len); /* start with inner pad */ + SHA256_Final(digest, &ctx); /* finish up 1st pass */ +} + +/* KDF + * Length of output is in octets rather than bits + * since length is always a multiple of 8 + * output array is organized so first N octets starting from 0 + * contains PRF output + * + * supported inputs are 16, 32, 48, 64 + * output array must be 80 octets in size to allow for sha1 overflow + */ +#define KDF_MAX_I_D_LEN 128 +int +KDF(unsigned char *key, int key_len, unsigned char *prefix, + int prefix_len, unsigned char *data, int data_len, + unsigned char *output, int len) +{ + unsigned char input[KDF_MAX_I_D_LEN]; /* concatenated input */ + int total_len; + int data_offset = 0; + + if ((prefix_len + data_len + 1) > KDF_MAX_I_D_LEN) + return (-1); + + if (prefix_len != 0) { + bcopy(prefix, input, prefix_len); + data_offset = prefix_len; + } + bcopy(data, &input[data_offset], data_len); + total_len = data_offset + data_len; + hmac_sha256_n(key, key_len, input, total_len, output, len); + return (0); +} diff --git a/release/src-rt/bcmcrypto/md32_common.h b/release/src-rt/bcmcrypto/md32_common.h new file mode 100755 index 0000000000..10eda0bd80 --- /dev/null +++ b/release/src-rt/bcmcrypto/md32_common.h @@ -0,0 +1,602 @@ +/* crypto/md32_common.h */ +/* ==================================================================== + * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at lest 32 bit wide, if it's wider, then + * HASH_LONG_LOG2 *has to* be defined along + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * HASH_LONG data[HASH_LBLOCK]; + * unsigned int num; + * ... + * } HASH_CTX; + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_HOST_ORDER + * name of "block" function treating *aligned* input message + * in host byte order, implemented externally. + * HASH_BLOCK_DATA_ORDER + * name of "block" function treating *unaligned* input message + * in original (data) byte order, implemented externally (it + * actually is optional if data and host are of the same + * "endianess"). + * HASH_MAKE_STRING + * macro convering context variables to an ASCII hash string. + * + * Optional macros: + * + * B_ENDIAN or L_ENDIAN + * defines host byte-order. + * HASH_LONG_LOG2 + * defaults to 2 if not states otherwise. + * HASH_LBLOCK + * assumed to be HASH_CBLOCK/4 if not stated otherwise. + * HASH_BLOCK_DATA_ORDER_ALIGNED + * alternative "block" function capable of treating + * aligned input message in original (data) order, + * implemented externally. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_LONG_LOG2 MD5_LONG_LOG2 + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_LBLOCK MD5_LBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_HOST_ORDER md5_block_host_order + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + * + * + */ + +/* FILE-CSTYLED */ + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +#error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_HOST_ORDER +#error "HASH_BLOCK_HOST_ORDER must be defined!" +#endif + + +#ifndef HASH_LBLOCK +#define HASH_LBLOCK (HASH_CBLOCK/4) +#endif + +#ifndef HASH_LONG_LOG2 +#define HASH_LONG_LOG2 2 +#endif + +/* + * Engage compiler specific rotate intrinsic function if available. + */ +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) || defined(__ICC) +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__MWERKS__) +# if defined(__POWERPC__) +# define ROTATE(a,n) __rlwinm(a,n,0,31) +# elif defined(__MC68K__) + /* Motorola specific tweak. */ +# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) +# else +# define ROTATE(a,n) __rol(a,n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && \ + !defined(OPENSSL_NO_INLINE_ASM) + /* + * Some GNU C inline assembler templates. Note that these are + * rotates by *constant* number of bits! But that's exactly + * what we need here... + * + */ +# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# elif defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "rlwinm %0,%1,%2,0,31" \ + : "=r"(ret) \ + : "r"(a), "I"(n)); \ + ret; \ + }) +# endif +# endif +#endif /* PEDANTIC */ + +#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ +/* A nice byte order reversal from Wei Dai */ +#ifdef ROTATE +/* 5 instructions with rotate instruction, else 9 */ +#define REVERSE_FETCH32(a,l) ( \ + l =* (const HASH_LONG *)(a), \ + ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ + ) +#else +/* 6 instructions with rotate instruction, else 8 */ +#define REVERSE_FETCH32(a,l) ( \ + l =* (const HASH_LONG *)(a), \ + l = (((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ + ROTATE(l,16) \ + ) +/* + * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... + * It's rewritten as above for two reasons: + * - RISCs aren't good at long constants and have to explicitely + * compose 'em with several (well, usually 2) instructions in a + * register before performing the actual operation and (as you + * already realized:-) having same constant should inspire the + * compiler to permanently allocate the only register for it; + * - most modern CPUs have two ALUs, but usually only one has + * circuitry for shifts:-( this minor tweak inspires compiler + * to schedule shift instructions in a better way... + * + * + */ +#endif +#endif + +#ifndef ROTATE +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* + * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED + * and HASH_BLOCK_HOST_ORDER ought to be the same if input data + * and host are of the same "endianess". It's possible to mask + * this with blank #define HASH_BLOCK_DATA_ORDER though... + * + * + */ +#if defined(B_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# endif +#elif defined(L_ENDIAN) +# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# endif +#endif + +#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && \ + !defined(OPENSSL_NO_INLINE_ASM) +# if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \ + (defined(__x86_64) || defined(__x86_64__)) + /* + * This gives ~30-40% performance improvement in SHA-256 compiled + * with gcc [on P4]. Well, first macro to be frank. We can pull + * this trick on x86* platforms only, because these CPUs can fetch + * unaligned data without raising an exception. + */ +# define HOST_c2l(c,l) ({ unsigned int r=*((const unsigned int *)(c)); \ + asm ("bswapl %0":"=r"(r):"0"(r)); \ + (c)+=4; (l)=r; }) +# define HOST_l2c(l,c) ({ unsigned int r=(l); \ + asm ("bswapl %0":"=r"(r):"0"(r)); \ + *((unsigned int *)(c))=r; (c)+=4; r; }) +# endif +# endif +#endif + +#ifndef HOST_c2l +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ), \ + l) +#endif +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } } +#ifndef HOST_l2c +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) +#endif + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# ifndef B_ENDIAN + /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */ +# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l) +# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l) +# endif +#endif + +#ifndef HOST_c2l +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24), \ + l) +#endif +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } } +#ifndef HOST_l2c +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) +#endif + +#endif + +/* + * Time for some action:-) + */ + +int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len) + { + const unsigned char *data=data_; + register HASH_LONG * p; + register HASH_LONG l; + size_t sw,sc,ew,ec; + + if (len==0) return 1; + + l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); /* might cause compiler warning on 16-bit */ + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= HASH_CBLOCK) + { + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; swnum); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=(unsigned int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + if (sc) + l=p[sw]; + HOST_p_c2l(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + if (ec) + { + HOST_c2l_p(data,l,ec); p[sw]=l; + } + } + return 1; + } + } + + sw=len/HASH_CBLOCK; + if (sw > 0) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + /* + * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined + * only if sizeof(HASH_LONG)==4. + */ + if ((((size_t)data)%4) == 0) + { + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } + else +#if !defined(HASH_BLOCK_DATA_ORDER) + while (sw--) + { + memcpy (p=c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); + data+=HASH_CBLOCK; + len-=HASH_CBLOCK; + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + { + HASH_BLOCK_DATA_ORDER(c,data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } +#endif + } + + if (len!=0) + { + p = c->data; + c->num = len; + ew=len>>2; /* words to copy */ + ec=len&0x03; + for (; ew; ew--,p++) + { + HOST_c2l(data,l); *p=l; + } + HOST_c2l_p(data,l,ec); + *p=l; + } + return 1; + } + + +void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + if ((((size_t)data)%4) == 0) + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,1); + else +#if !defined(HASH_BLOCK_DATA_ORDER) + { + memcpy (c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + HASH_BLOCK_DATA_ORDER (c,data,1); +#endif + } + + +int HASH_FINAL (unsigned char *md, HASH_CTX *c) + { + register HASH_LONG *p; + register unsigned long l; + register int i,j; + static const unsigned char end[4]={0x80,0x00,0x00,0x00}; + const unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + i=c->num>>2; + j=c->num&0x03; + + l = (j==0) ? 0 : p[i]; + HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ + + if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ + { + if (iNh; + p[HASH_LBLOCK-1]=c->Nl; +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + p[HASH_LBLOCK-2]=c->Nl; + p[HASH_LBLOCK-1]=c->Nh; +#endif + HASH_BLOCK_HOST_ORDER (c,p,1); + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c,md); +#endif + + c->num=0; + /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack + * but I'm not worried :-) + OPENSSL_cleanse((void *)c,sizeof(HASH_CTX)); + */ + return 1; + } + +#ifndef MD32_REG_T +#define MD32_REG_T long +/* + * This comment was originaly written for MD5, which is why it + * discusses A-D. But it basically applies to all 32-bit digests, + * which is why it was moved to common header file. + * + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * Apparently there're LP64 compilers that generate better + * code if A-D are declared int. Most notably GCC-x86_64 + * generates better code. + * + */ +#endif diff --git a/release/src-rt/bcmcrypto/md4.c b/release/src-rt/bcmcrypto/md4.c new file mode 100755 index 0000000000..8934ca07e0 --- /dev/null +++ b/release/src-rt/bcmcrypto/md4.c @@ -0,0 +1,287 @@ +/* + * md4.c, copied from src/router/ppp/pppd to src/bcmcrypto for general use, + * with a few casts added to make it usable with a fussy compiler. + * + * ******************************************************************** + * md4.c -- Implementation of MD4 Message Digest Algorithm ** + * Updated: 2/16/90 by Ronald L. Rivest ** + * (C) 1990 RSA Data Security, Inc. ** + * ******************************************************************** + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: md4.c,v 1.5 2006-06-14 21:07:54 Exp $ + */ + +/* + * To use MD4: + * -- Include md4.h in your program + * -- Declare an MDstruct MD to hold the state of the digest + * computation. + * -- Initialize MD using MDbegin(&MD) + * -- For each full block (64 bytes) X you wish to process, call + * MD4Update(&MD,X,512) + * (512 is the number of bits in a full block.) + * -- For the last block (less than 64 bytes) you wish to process, + * MD4Update(&MD,X,n) + * where n is the number of bits in the partial block. A partial + * block terminates the computation, so every MD computation + * should terminate by processing a partial block, even if it + * has n = 0. + * -- The message digest is available in MD.buffer[0] ... + * MD.buffer[3]. (Least-significant byte of each word + * should be output first.) + * -- You can print out the digest using MDprint(&MD) + */ + +/* Implementation notes: + * This implementation assumes that ints are 32-bit quantities. + */ + +#include + +#include + +#ifndef BCMDRIVER +#include +#endif + +/* Compile-time declarations of MD4 "magic constants". */ +#define I0 0x67452301 /* Initial values for MD buffer */ +#define I1 0xefcdab89 +#define I2 0x98badcfe +#define I3 0x10325476 +#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ +#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ +/* C2 and C3 are from Knuth, The Art of Programming, Volume 2 + * (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. + * Table 2, page 660. + */ + +#define fs1 3 /* round 1 shift amounts */ +#define fs2 7 +#define fs3 11 +#define fs4 19 +#define gs1 3 /* round 2 shift amounts */ +#define gs2 5 +#define gs3 9 +#define gs4 13 +#define hs1 3 /* round 3 shift amounts */ +#define hs2 9 +#define hs3 11 +#define hs4 15 + +/* Compile-time macro declarations for MD4. + * Note: The "rot" operator uses the variable "tmp". + * It assumes tmp is declared as unsigned int, so that the >> + * operator will shift in zeros rather than extending the sign bit. + */ +#define f(X, Y, Z) ((X & Y) | ((~X) & Z)) +#define g(X, Y, Z) ((X & Y) | (X & Z) | (Y & Z)) +#define h(X, Y, Z) (X ^ Y ^ Z) +#define rot(X, S) (tmp = X, (tmp << S) | (tmp >> (32 - S))) +#define ff(A, B, C, D, i, s) A = rot((A + f(B, C, D) + X[i]), s) +#define gg(A, B, C, D, i, s) A = rot((A + g(B, C, D) + X[i] + C2), s) +#define hh(A, B, C, D, i, s) A = rot((A + h(B, C, D) + X[i] + C3), s) + + +/* MD4Init(MDp) + * Initialize message digest buffer MDp. + * This is a user-callable routine. + */ +void +BCMROMFN(MD4Init)(MD4_CTX *MDp) +{ + int i; + MDp->buffer[0] = I0; + MDp->buffer[1] = I1; + MDp->buffer[2] = I2; + MDp->buffer[3] = I3; + for (i = 0; i < 8; i++) + MDp->count[i] = 0; + MDp->done = 0; +} + +/* MDblock(MDp,X) + * Update message digest buffer MDp->buffer using 16-word data block X. + * Assumes all 16 words of X are full of data. + * Does not update MDp->count. + * This routine is not user-callable. + */ +static void +MDblock(MD4_CTX *MDp, unsigned char *Xb) +{ + register unsigned int tmp, A, B, C, D; + unsigned int X[16]; + int i; + + for (i = 0; i < 16; ++i) { + X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24); + Xb += 4; + } + + A = MDp->buffer[0]; + B = MDp->buffer[1]; + C = MDp->buffer[2]; + D = MDp->buffer[3]; + /* Update the message digest buffer */ + ff(A, B, C, D, 0, fs1); /* Round 1 */ + ff(D, A, B, C, 1, fs2); + ff(C, D, A, B, 2, fs3); + ff(B, C, D, A, 3, fs4); + ff(A, B, C, D, 4, fs1); + ff(D, A, B, C, 5, fs2); + ff(C, D, A, B, 6, fs3); + ff(B, C, D, A, 7, fs4); + ff(A, B, C, D, 8, fs1); + ff(D, A, B, C, 9, fs2); + ff(C, D, A, B, 10, fs3); + ff(B, C, D, A, 11, fs4); + ff(A, B, C, D, 12, fs1); + ff(D, A, B, C, 13, fs2); + ff(C, D, A, B, 14, fs3); + ff(B, C, D, A, 15, fs4); + gg(A, B, C, D, 0, gs1); /* Round 2 */ + gg(D, A, B, C, 4, gs2); + gg(C, D, A, B, 8, gs3); + gg(B, C, D, A, 12, gs4); + gg(A, B, C, D, 1, gs1); + gg(D, A, B, C, 5, gs2); + gg(C, D, A, B, 9, gs3); + gg(B, C, D, A, 13, gs4); + gg(A, B, C, D, 2, gs1); + gg(D, A, B, C, 6, gs2); + gg(C, D, A, B, 10, gs3); + gg(B, C, D, A, 14, gs4); + gg(A, B, C, D, 3, gs1); + gg(D, A, B, C, 7, gs2); + gg(C, D, A, B, 11, gs3); + gg(B, C, D, A, 15, gs4); + hh(A, B, C, D, 0, hs1); /* Round 3 */ + hh(D, A, B, C, 8, hs2); + hh(C, D, A, B, 4, hs3); + hh(B, C, D, A, 12, hs4); + hh(A, B, C, D, 2, hs1); + hh(D, A, B, C, 10, hs2); + hh(C, D, A, B, 6, hs3); + hh(B, C, D, A, 14, hs4); + hh(A, B, C, D, 1, hs1); + hh(D, A, B, C, 9, hs2); + hh(C, D, A, B, 5, hs3); + hh(B, C, D, A, 13, hs4); + hh(A, B, C, D, 3, hs1); + hh(D, A, B, C, 11, hs2); + hh(C, D, A, B, 7, hs3); + hh(B, C, D, A, 15, hs4); + MDp->buffer[0] += A; + MDp->buffer[1] += B; + MDp->buffer[2] += C; + MDp->buffer[3] += D; +} + +/* MD4Update(MDp,X,count) + * Input: X -- a pointer to an array of unsigned characters. + * count -- the number of bits of X to use. + * (if not a multiple of 8, uses high bits of last byte.) + * Update MDp using the number of bits of X given by count. + * This is the basic input routine for an MD4 user. + * The routine completes the MD computation when count < 512, so + * every MD computation should end with one call to MD4Update with a + * count less than 512. A call with count 0 will be ignored if the + * MD has already been terminated (done != 0), so an extra call with + * count 0 can be given as a "courtesy close" to force termination + * if desired. + */ +void +BCMROMFN(MD4Update)(MD4_CTX *MDp, unsigned char *X, unsigned int count) +{ + unsigned int i, tmp, bit, byte, mask; + unsigned char XX[64]; + unsigned char *p; + + /* return with no error if this is a courtesy close with count + * zero and MDp->done is true. + */ + if (count == 0 && MDp->done) return; + /* check to see if MD is already done and report error */ + if (MDp->done) { + return; + } + + /* Add count to MDp->count */ + tmp = count; + p = MDp->count; + while (tmp) { + tmp += *p; + *p++ = (unsigned char) tmp; + tmp = tmp >> 8; + } + + /* Process data */ + if (count == 512) { + /* Full block of data to handle */ + MDblock(MDp, X); + } else if (count > 512) { + /* Check for count too large */ + return; + } else { + /* partial block -- must be last block so finish up */ + + /* Find out how many bytes and residual bits there are */ + byte = count >> 3; + bit = count & 7; + /* Copy X into XX since we need to modify it */ + for (i = 0; i <= byte; i++) + XX[i] = X[i]; + for (i = byte + 1; i < 64; i++) + XX[i] = 0; + /* Add padding '1' bit and low-order zeros in last byte */ + mask = 1 << (7 - bit); + XX[byte] = (XX[byte] | mask) & ~(mask - 1); + /* If room for bit count, finish up with this block */ + if (byte <= 55) { + for (i = 0; i < 8; i++) + XX[56 + i] = MDp->count[i]; + MDblock(MDp, XX); + } else { + /* need to do two blocks to finish up */ + MDblock(MDp, XX); + for (i = 0; i < 56; i++) + XX[i] = 0; + for (i = 0; i < 8; i++) + XX[56 + i] = MDp->count[i]; + MDblock(MDp, XX); + } + /* Set flag saying we're done with MD computation */ + MDp->done = 1; + } +} + +/* + * Finish up MD4 computation and return message digest. + */ +void +BCMROMFN(MD4Final)(unsigned char *buf, MD4_CTX *MD) +{ + int i, j; + unsigned int w; + + MD4Update(MD, NULL, 0); + for (i = 0; i < 4; ++i) { + w = MD->buffer[i]; + for (j = 0; j < 4; ++j) { + *buf++ = (unsigned char) w; + w >>= 8; + } + } +} + +/* + * End of md4.c + */ diff --git a/release/src-rt/bcmcrypto/md5.c b/release/src-rt/bcmcrypto/md5.c new file mode 100755 index 0000000000..dd3f444bf2 --- /dev/null +++ b/release/src-rt/bcmcrypto/md5.c @@ -0,0 +1,323 @@ +/* + * md5.c, copied from src/router/ppp/pppd to src/bcmcrypto for general use, + * with a few casts added to make it usable with a fussy compiler. + * + * md5.c -- the source code for MD5 routines + * RSA Data Security, Inc. MD5 Message-Digest Algorithm + * Created: 2/17/90 RLR + * Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. + */ + +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD5 Message- + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD5 Message-Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: md5.c,v 1.12 2007-03-26 17:28:56 Exp $ + */ + +#ifdef BCMDRIVER +#include +#include +#else +#if defined(__GNUC__) +#include +#endif +#endif /* BCMDRIVER */ + +#include + +typedef uint32 UINT4; + +/* + * Message-digest routines: + * To form the message digest for a message M + * (1) Initialize a context buffer mdContext using MD5Init + * (2) Call MD5Update on mdContext and M + * (3) Call MD5Final on mdContext + * The message digest is now in mdContext->digest[0...15] + * + */ + +/* forward declaration */ +static void Transform(UINT4 *buf, UINT4 *in); + +static const unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ +{ \ + (a) += F((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ +} +#define GG(a, b, c, d, x, s, ac) \ +{ \ + (a) += G((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ +} +#define HH(a, b, c, d, x, s, ac) \ +{ \ + (a) += H((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ +} +#define II(a, b, c, d, x, s, ac) \ +{ \ + (a) += I((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ +} + +#ifndef UL +#ifdef __STDC__ +#define UL(x) x##U +#else +#define UL(x) x +#endif +#endif /* !UL */ + +/* The routine MD5Init initializes the message-digest context + * mdContext. All fields are set to zero. + */ +void +BCMROMFN(MD5Init)(MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + +/* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +/* The routine MD5Update updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +void +BCMROMFN(MD5Update)(MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + +/* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + +/* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { +/* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + +/* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform(mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + */ +void +BCMROMFN(MD5Final)(unsigned char *hash, MD5_CTX *mdContext) +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + +/* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + +/* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + +/* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update(mdContext, PADDING, padLen); + +/* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform(mdContext->buf, in); + +/* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + memcpy((void *)hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void +Transform(UINT4 *buf, UINT4 *in) +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + +/* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF(a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF(d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF(c, d, a, b, in[ 2], S13, UL(606105819)); /* 3 */ + FF(b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF(a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF(d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF(c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF(b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF(a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF(d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF(c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF(b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF(a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF(d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF(c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF(b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + +/* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG(a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG(d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG(c, d, a, b, in[11], S23, UL(643717713)); /* 19 */ + GG(b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG(a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG(d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG(c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG(b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG(a, b, c, d, in[ 9], S21, UL(568446438)); /* 25 */ + GG(d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG(c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG(b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG(a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG(d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG(c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG(b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + +/* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH(a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH(d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH(c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH(b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH(a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH(d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH(c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH(b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH(a, b, c, d, in[13], S31, UL(681279174)); /* 41 */ + HH(d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH(c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH(b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH(a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH(d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH(c, d, a, b, in[15], S33, UL(530742520)); /* 47 */ + HH(b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + +/* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II(a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II(d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II(c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II(b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II(a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II(d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II(c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II(b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II(a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II(d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II(c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II(b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II(a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II(d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II(c, d, a, b, in[ 2], S43, UL(718787259)); /* 63 */ + II(b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * End of md5.c + */ diff --git a/release/src-rt/bcmcrypto/passhash.c b/release/src-rt/bcmcrypto/passhash.c new file mode 100755 index 0000000000..d8ac4079e7 --- /dev/null +++ b/release/src-rt/bcmcrypto/passhash.c @@ -0,0 +1,274 @@ +/* + * passhash.c + * Perform password to key hash algorithm as defined in WPA and 802.11i + * specifications + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: passhash.c,v 1.18.230.2 2010-12-01 23:33:28 Exp $ + */ + +#include +#include +#include + +#ifdef BCMDRIVER +#include +#else +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, size_t len); +extern int bcmp(const void *b1, const void *b2, size_t len); +extern void bzero(void *b, size_t len); +extern size_t strlen(const char *s); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif +#endif /* BCMDRIVER */ + +#ifdef BCMPASSHASH_TEST +#include +void prhash(char *password, int passlen, unsigned char *ssid, int ssidlen, unsigned char *output); +#define dbg(args) printf args +#endif /* BCMPASSHASH_TEST */ + +/* F(P, S, c, i) = U1 xor U2 xor ... Uc + * U1 = PRF(P, S || Int(i) + * U2 = PRF(P, U1) + * Uc = PRF(P, Uc-1) + */ +static void +F(char *password, int passlen, unsigned char *ssid, int ssidlength, int iterations, int count, + unsigned char *output) +{ + unsigned char digest[36], digest1[SHA1HashSize]; + int i, j; + + /* U1 = PRF(P, S || int(i)) */ + if (ssidlength > 32) + ssidlength = 32; + bcopy(ssid, digest, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + hmac_sha1(digest, ssidlength+4, (unsigned char *)password, passlen, digest1); + + /* output = U1 */ + bcopy(digest1, output, SHA1HashSize); + + for (i = 1; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + hmac_sha1(digest1, SHA1HashSize, (unsigned char *)password, passlen, digest); + bcopy(digest, digest1, SHA1HashSize); + + /* output = output xor Un */ + for (j = 0; j < SHA1HashSize; j++) { + output[j] ^= digest[j]; + } + } +} + +/* passhash: perform passwork->key hash algorithm as defined in WPA and 802.11i + * specifications. + * password is an ascii string of 8 to 63 characters in length + * ssid is up to 32 bytes + * ssidlen is the length of ssid in bytes + * output must be at lest 40 bytes long, and returns a 256 bit key + * returns 0 on success, non-zero on failure + */ +int +BCMROMFN(passhash)(char *password, int passlen, unsigned char *ssid, int ssidlen, + unsigned char *output) +{ + if ((strlen(password) < 8) || (strlen(password) > 63) || (ssidlen > 32)) return 1; + + F(password, passlen, ssid, ssidlen, 4096, 1, output); + F(password, passlen, ssid, ssidlen, 4096, 2, &output[SHA1HashSize]); + return 0; +} + +static void +init_F(char *password, int passlen, unsigned char *ssid, int ssidlength, + int count, unsigned char *lastdigest, unsigned char *output) +{ + unsigned char digest[36]; + + /* U0 = PRF(P, S || int(i)) */ + /* output = U0 */ + if (ssidlength > 32) + ssidlength = 32; + bcopy(ssid, digest, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + hmac_sha1(digest, ssidlength+4, (unsigned char *)password, passlen, output); + + /* Save U0 for next PRF() */ + bcopy(output, lastdigest, SHA1HashSize); +} + +static void +do_F(char *password, int passlen, int iterations, unsigned char *lastdigest, unsigned char *output) +{ + unsigned char digest[SHA1HashSize]; + int i, j; + + for (i = 0; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + hmac_sha1(lastdigest, SHA1HashSize, (unsigned char *)password, passlen, digest); + /* output = output xor Un */ + for (j = 0; j < SHA1HashSize; j++) + output[j] ^= digest[j]; + + /* Save Un for next PRF() */ + bcopy(digest, lastdigest, SHA1HashSize); + } +} + +/* passhash: Perform passwork to key hash algorithm as defined in WPA and 802.11i + * specifications. We are breaking this lengthy process into smaller pieces. Users + * are responsible for making sure password length is between 8 and 63 inclusive. + * + * init_passhash: initialize passhash_t structure. + * do_passhash: advance states in passhash_t structure and return 0 to indicate + * it is done and 1 to indicate more to be done. + * get_passhash: copy passhash result to output buffer. + */ +int +init_passhash(passhash_t *ph, + char *password, int passlen, unsigned char *ssid, int ssidlen) +{ + if (strlen(password) < 8 || strlen(password) > 63) + return -1; + + bzero(ph, sizeof(*ph)); + ph->count = 1; + ph->password = password; + ph->passlen = passlen; + ph->ssid = ssid; + ph->ssidlen = ssidlen; + + return 0; +} + +int +do_passhash(passhash_t *ph, int iterations) +{ + unsigned char *output; + + if (ph->count > 2) + return -1; + output = ph->output + SHA1HashSize * (ph->count - 1); + if (ph->iters == 0) { + init_F(ph->password, ph->passlen, ph->ssid, ph->ssidlen, + ph->count, ph->digest, output); + ph->iters = 1; + iterations --; + } + if (ph->iters + iterations > 4096) + iterations = 4096 - ph->iters; + do_F(ph->password, ph->passlen, iterations, ph->digest, output); + ph->iters += iterations; + if (ph->iters == 4096) { + ph->count ++; + ph->iters = 0; + if (ph->count > 2) + return 0; + } + return 1; +} + +int +get_passhash(passhash_t *ph, unsigned char *output, int outlen) +{ + if (ph->count > 2 && outlen <= (int)sizeof(ph->output)) { + bcopy(ph->output, output, outlen); + return 0; + } + return -1; +} + +#ifdef BCMPASSHASH_TEST +void +prhash(char *password, int passlen, unsigned char *ssid, int ssidlen, unsigned char *output) +{ + int k; + printf("pass\n\t%s\nssid(hex)\n\t", password); + for (k = 0; k < ssidlen; k++) { + printf("%02x ", ssid[k]); + if (!((k+1)%16)) printf("\n\t"); + } + printf("\nhash\n\t"); + for (k = 0; k < 2 * SHA1HashSize; k++) { + printf("%02x ", output[k]); + if (!((k + 1) % SHA1HashSize)) printf("\n\t"); + } + printf("\n"); +} + +#include "passhash_vectors.h" + +int main(int argc, char **argv) +{ + unsigned char output[2*SHA1HashSize]; + int retv, k, fail = 0, fail1 = 0; + passhash_t passhash_states; + + dbg(("%s: testing passhash()\n", *argv)); + + for (k = 0; k < NUM_PASSHASH_VECTORS; k++) { + printf("Passhash test %d:\n", k); + bzero(output, sizeof(output)); + retv = passhash(passhash_vec[k].pass, passhash_vec[k].pl, + passhash_vec[k].salt, passhash_vec[k].sl, output); + prhash(passhash_vec[k].pass, passhash_vec[k].pl, + passhash_vec[k].salt, passhash_vec[k].sl, output); + + if (retv) { + dbg(("%s: passhash() test %d returned error\n", *argv, k)); + fail++; + } + if (bcmp(output, passhash_vec[k].ref, 2*SHA1HashSize) != 0) { + dbg(("%s: passhash test %d reference mismatch\n", *argv, k)); + fail++; + } + } + + dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED")); + + dbg(("%s: testing init_passhash()/do_passhash()/get_passhash()\n", *argv)); + + for (k = 0; k < NUM_PASSHASH_VECTORS; k++) { + printf("Passhash test %d:\n", k); + init_passhash(&passhash_states, + passhash_vec[k].pass, passhash_vec[k].pl, + passhash_vec[k].salt, passhash_vec[k].sl); + while ((retv = do_passhash(&passhash_states, 100)) > 0) + ; + get_passhash(&passhash_states, output, sizeof(output)); + prhash(passhash_vec[k].pass, passhash_vec[k].pl, + passhash_vec[k].salt, passhash_vec[k].sl, output); + + if (retv < 0) { + dbg(("%s: passhash() test %d returned error\n", *argv, k)); + fail1++; + } + if (bcmp(output, passhash_vec[k].ref, 2*SHA1HashSize) != 0) { + dbg(("%s: passhash test %d reference mismatch\n", *argv, k)); + fail1++; + } + } + + dbg(("%s: %s\n", *argv, fail1?"FAILED":"PASSED")); + return (fail+fail1); +} +#endif /* BCMPASSHASH_TEST */ diff --git a/release/src-rt/bcmcrypto/passhash_vectors.h b/release/src-rt/bcmcrypto/passhash_vectors.h new file mode 100755 index 0000000000..a697269aa0 --- /dev/null +++ b/release/src-rt/bcmcrypto/passhash_vectors.h @@ -0,0 +1,268 @@ +/* + * passhash_vectors.h + * Password Hash test vectors + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: passhash_vectors.h,v 1.4 2007-01-11 19:43:26 Exp $ + */ + +#include + +/* Make sure all passphrases and salts are null-terminated so we can get + * the sizes using sizeof(x) - 1 + */ +char pass_01[] = "password"; + +uint8 salt_01[] = "IEEE"; + +uint8 ref_01[] = { + 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef, + 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90, + 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2, + 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e, + 0x48, 0x88, 0xf1, 0x97, 0xa3, 0x68, 0x04, 0x15 + }; + +char pass_02[] = "ThisIsAPassword"; + +uint8 salt_02[] = "ThisIsASSID"; + +uint8 ref_02[] = { + 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6, + 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3, + 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08, + 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf, + 0xca, 0xc2, 0x80, 0x6d, 0xe3, 0xfd, 0x47, 0xa8 + }; + +char pass_03[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + +uint8 salt_03[] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; + +uint8 ref_03[] = { + 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83, + 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c, + 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48, + 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62, + 0x1d, 0x20, 0xbd, 0x88, 0x0f, 0x55, 0x2c, 0xbb + }; + +char pass_04[] = "password"; + +uint8 salt_04[] = { 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12, 0x00 }; + +uint8 ref_04[] = { + 0x08, 0x79, 0xef, 0x3a, 0x9e, 0xa7, 0xe0, 0x66, + 0x05, 0x39, 0x7f, 0xb4, 0x11, 0xb8, 0xf9, 0xf7, + 0x90, 0x7b, 0x24, 0xd2, 0xa0, 0x31, 0x01, 0x33, + 0x31, 0x40, 0x8a, 0x42, 0xde, 0xe2, 0x28, 0x26, + 0x1e, 0x3d, 0x64, 0x13, 0xc0, 0xb0, 0xe9, 0x8f + }; + +char pass_05[] = "passphrase!"; + +uint8 salt_05[] = "wpa_psk"; + +uint8 ref_05[] = { + 0x08, 0xa3, 0x94, 0x8b, 0x74, 0x8d, 0xda, 0x04, + 0xdf, 0xd2, 0x4b, 0x4a, 0xda, 0x23, 0x1e, 0xbf, + 0xe5, 0xdd, 0x38, 0xd3, 0x9a, 0xdd, 0x54, 0xa6, + 0xc9, 0xed, 0x2a, 0x6c, 0x2c, 0x62, 0xc5, 0x15, + 0xa2, 0xb7, 0x3d, 0xc3, 0xd9, 0x53, 0x0f, 0xf0 + }; + +char pass_06[] = "PASSPHRASE"; + +uint8 salt_06[] = "wpa_psk"; + +uint8 ref_06[] = { + 0x2c, 0x84, 0x30, 0x3a, 0x59, 0x3b, 0x91, 0x7f, + 0x5a, 0x9f, 0x53, 0x73, 0xc8, 0x5f, 0xe0, 0x1c, + 0x57, 0x87, 0xda, 0x02, 0xb0, 0x3f, 0xc0, 0x3c, + 0x09, 0x76, 0xe1, 0x52, 0x6f, 0x9d, 0xcc, 0x13, + 0x9d, 0xb4, 0x79, 0x46, 0x98, 0xdd, 0x51, 0x63 + }; + +char pass_07[] = "PASSPHRASE1"; + +uint8 salt_07[] = "wpa_psk"; + +uint8 ref_07[] = { + 0xf9, 0xdb, 0xe5, 0x4b, 0x58, 0xb2, 0xb0, 0xce, + 0x8f, 0x6e, 0xa3, 0xe4, 0xa4, 0xcd, 0xc6, 0x4b, + 0x11, 0x24, 0xab, 0x80, 0x32, 0x69, 0x32, 0x8e, + 0xea, 0xef, 0x9c, 0x26, 0x65, 0x2d, 0x9f, 0x60, + 0x49, 0x52, 0x48, 0x47, 0x02, 0x1d, 0x75, 0xe8 + }; + +char pass_08[] = "PASSPHRASE11"; + +uint8 salt_08[] = "wpa_psk"; + +uint8 ref_08[] = { + 0x65, 0x4d, 0x60, 0xa5, 0x24, 0xb7, 0xa8, 0xec, + 0x12, 0xa5, 0xeb, 0x01, 0x9d, 0xa9, 0xda, 0x1f, + 0xd0, 0x82, 0x92, 0x8f, 0xfe, 0x13, 0x6f, 0x1a, + 0x9b, 0x8a, 0x7f, 0xe9, 0x92, 0x74, 0xba, 0xbb, + 0x86, 0xef, 0x50, 0x50, 0x8d, 0xe3, 0x59, 0xc1 + }; + +char pass_09[] = "PASSPHRASE111"; + +uint8 salt_09[] = "wpa_psk"; + +uint8 ref_09[] = { + 0xac, 0xb8, 0x2e, 0xfd, 0x02, 0xf1, 0xa3, 0x6c, + 0x99, 0xe9, 0x21, 0x16, 0x30, 0xcf, 0x11, 0x96, + 0x7e, 0x26, 0x0b, 0x01, 0x26, 0xb0, 0x12, 0x45, + 0xc6, 0xd2, 0x65, 0xed, 0x1c, 0x40, 0xe2, 0xf9, + 0x3a, 0xc4, 0x5c, 0x80, 0x5a, 0xf9, 0x48, 0xe4 + }; + +char pass_10[] = "PASSPHRASE1111"; + +uint8 salt_10[] = "wpa_psk"; + +uint8 ref_10[] = { + 0x0f, 0xba, 0xf8, 0x61, 0xa5, 0xf0, 0x9f, 0xc7, + 0xec, 0xda, 0xb6, 0x7e, 0x0d, 0x11, 0x63, 0xbe, + 0xb2, 0x01, 0x91, 0xa1, 0xba, 0xce, 0x08, 0xd1, + 0xf8, 0x2e, 0xaa, 0x7a, 0x02, 0xc1, 0x0e, 0x1e, + 0x22, 0x2c, 0x42, 0x3f, 0xf0, 0xfe, 0xd1, 0x78 + }; + +char pass_11[] = "*Doyouknowtheway"; + +uint8 salt_11[] = "wpa"; + +uint8 ref_11[] = { + 0x0e, 0xdb, 0xaa, 0x85, 0x68, 0x3a, 0x8d, 0xc0, + 0x84, 0x58, 0x97, 0x54, 0x79, 0x97, 0x48, 0x86, + 0x5a, 0x2b, 0x63, 0xa6, 0x42, 0x8c, 0x65, 0x91, + 0x59, 0x88, 0xe9, 0x24, 0x30, 0xe4, 0xf8, 0x33, + 0x7c, 0x63, 0xda, 0x22, 0x96, 0xee, 0xa5, 0x4d + }; + +char pass_12[] = "ToSanJose&&"; + +uint8 salt_12[] = "wpa"; + +uint8 ref_12[] = { + 0xef, 0x1b, 0x56, 0xee, 0xca, 0xdb, 0x92, 0xcc, + 0x4a, 0x5e, 0x42, 0x29, 0xcf, 0x13, 0xba, 0x6b, + 0x4d, 0x12, 0x0d, 0x19, 0x4a, 0x48, 0xc6, 0xb9, + 0xa4, 0xf8, 0xa8, 0x5c, 0x38, 0xea, 0x77, 0x30, + 0x01, 0x17, 0x80, 0xdc, 0xcb, 0x3f, 0x58, 0x00 + }; + +char pass_13[] = "I-Left-My-Heart"; + +uint8 salt_13[] = "802.11b"; + +uint8 ref_13[] = { + 0x0f, 0x11, 0xe3, 0x27, 0xb5, 0xaf, 0x29, 0xa5, + 0x02, 0x1a, 0x77, 0x70, 0x28, 0xed, 0xc7, 0x48, + 0x09, 0x96, 0x93, 0x35, 0x9c, 0xcf, 0xc9, 0xba, + 0x63, 0x29, 0xdb, 0xf5, 0x6d, 0x2f, 0xce, 0x5f, + 0xcf, 0x43, 0xd2, 0x4a, 0xe7, 0xdb, 0x7f, 0xd6 + }; + +char pass_14[] = "1nSanFranc1sc0"; + +uint8 salt_14[] = "802.11b"; + +uint8 ref_14[] = { + 0x5b, 0x93, 0xd9, 0x52, 0xa7, 0x7c, 0xa2, 0x42, + 0xd4, 0x59, 0x3b, 0x1f, 0x5a, 0xa3, 0xcf, 0x86, + 0x90, 0x6f, 0x44, 0x11, 0x4b, 0xd9, 0x82, 0xd5, + 0x4f, 0x1e, 0x91, 0xe9, 0xc4, 0xa4, 0x34, 0x8d, + 0x35, 0xfe, 0x1d, 0x4a, 0x49, 0xf2, 0x14, 0xca + }; + +char pass_15[] = "passphras"; + +uint8 salt_15[] = "wpa_psk"; + +uint8 ref_15[] = { + 0x35, 0x73, 0x10, 0xdd, 0xfc, 0x20, 0x51, 0x88, + 0xe5, 0xbd, 0x7a, 0xfd, 0x93, 0x7c, 0x3c, 0x80, + 0xce, 0x0f, 0xbe, 0x75, 0x23, 0xef, 0x89, 0x5e, + 0x26, 0xed, 0x9c, 0x5b, 0x1f, 0x5d, 0x5d, 0x9e, + 0xa3, 0x05, 0x1a, 0xc5, 0xcb, 0x63, 0xb3, 0xb6 + }; + +char pass_16[] = "1234567890123456789012345678901"; + +uint8 salt_16[] = "wpa_psk"; + +uint8 ref_16[] = { + 0x67, 0x8b, 0xb9, 0x3d, 0x34, 0xb6, 0x6a, 0xce, + 0x00, 0x0e, 0xba, 0x82, 0x24, 0x14, 0xe0, 0xe8, + 0xc3, 0x6f, 0x0b, 0x7c, 0x9b, 0x80, 0x5a, 0x5e, + 0x15, 0xa5, 0x58, 0x09, 0x67, 0x6f, 0x44, 0xe2, + 0x15, 0x1e, 0xa3, 0x73, 0x58, 0xc8, 0x60, 0x6a + }; + +char pass_17[] = "12345678901234567890123456789012"; + +uint8 salt_17[] = "wpa_psk"; + +uint8 ref_17[] = { + 0x72, 0x45, 0xd3, 0x12, 0x28, 0x2b, 0x8f, 0x62, + 0xda, 0x28, 0xeb, 0x0b, 0xef, 0x8f, 0x82, 0x1f, + 0x7c, 0x86, 0x6d, 0x39, 0x5b, 0xa7, 0x95, 0x67, + 0x1f, 0xef, 0x9e, 0x2b, 0xfa, 0x9d, 0xba, 0xff, + 0xcf, 0xe0, 0x2e, 0x28, 0xf0, 0x03, 0x9e, 0x04 + }; + +char pass_18[] = "123456789012345678901234567890123"; + +uint8 salt_18[] = "wpa_psk"; + +uint8 ref_18[] = { + 0x67, 0xc2, 0xda, 0x52, 0xf5, 0xd5, 0x56, 0x5a, + 0xc6, 0xf7, 0x4c, 0x52, 0x12, 0xd5, 0xde, 0xb1, + 0xc5, 0xd3, 0x6e, 0x8a, 0xde, 0x42, 0x9d, 0xb3, + 0x6f, 0x37, 0xf8, 0xf2, 0x12, 0x7d, 0xb6, 0x3e, + 0x02, 0x33, 0xb7, 0x86, 0x25, 0x10, 0x92, 0x19 + }; + +typedef struct { + int pl; + char *pass; + int sl; + uint8 *salt; + uint8 *ref; +} passhash_vector_t; + +#define PASSHASH_VECTOR_ENTRY(x) \ + { sizeof(pass_##x)-1, pass_##x, sizeof(salt_##x)-1, salt_##x, ref_##x } + +passhash_vector_t passhash_vec[] = { + PASSHASH_VECTOR_ENTRY(01), + PASSHASH_VECTOR_ENTRY(02), + PASSHASH_VECTOR_ENTRY(03), + PASSHASH_VECTOR_ENTRY(04), + PASSHASH_VECTOR_ENTRY(05), + PASSHASH_VECTOR_ENTRY(06), + PASSHASH_VECTOR_ENTRY(07), + PASSHASH_VECTOR_ENTRY(08), + PASSHASH_VECTOR_ENTRY(09), + PASSHASH_VECTOR_ENTRY(10), + PASSHASH_VECTOR_ENTRY(11), + PASSHASH_VECTOR_ENTRY(12), + PASSHASH_VECTOR_ENTRY(13), + PASSHASH_VECTOR_ENTRY(14), + PASSHASH_VECTOR_ENTRY(15), + PASSHASH_VECTOR_ENTRY(16), + PASSHASH_VECTOR_ENTRY(17), + PASSHASH_VECTOR_ENTRY(18) +}; +#define NUM_PASSHASH_VECTORS (sizeof(passhash_vec)/sizeof(passhash_vec[0])) diff --git a/release/src-rt/bcmcrypto/prebuilt/aes.o b/release/src-rt/bcmcrypto/prebuilt/aes.o deleted file mode 100644 index 7db4fb51d97cbd4b902de7b35bc2dc05eba97c62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 7392 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 O@CKMR${N7`2>2gD3%y?e diff --git a/release/src-rt/bcmcrypto/prebuilt/aeskeywrap.o b/release/src-rt/bcmcrypto/prebuilt/aeskeywrap.o deleted file mode 100644 index 54fb360934e53ba3eeb5966e342d5375f664d46b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 2768 zcwUWGO>7ip7=GrPc3CLMAdT5Xv@^KwteC7Dzyu8@&9;>gjX{V;FVfxaTB`loY!|ih z;G&Q~B$-A$NWy_^Thar`6k4H&QYWN`9z68Gfdh$q@ZiD3VmLGg^ZCB>vpc&DkvEyV z-~02uzt8OKH+}EEttbitQV>N$0v@#kTQnRy=t@aEgAO#)p2NTu)2LlmqyOG9ABkV= zb+K&!DQ??;h+FpW;%B=i7VHON-o7tx+V{i_dri#Q8kXo0aiij3H@?-3$r@rLYjoC$ z?<9Uf5h;piQ9O&{SrpHrcoxO8D4s>}EQ)7QJWHWFQPk88amVC)4`sKu1!DhSvbz(w zY&qxKa0pd%Luv^ltqVi%#uC-BbwgJjQRRB980Jm(C7Upk{eo>#MB;2CUn{9hnM>lD z#Xff{8dk)V9Yt?~{m37c80)H*5i7#cH5f6K^7P^*O+)6wE=Xk35?`b@Z z{eF{~=Xj2ZLn#^@_AHX?3XTJbu;z8_lw5K5N3e_7`XDqhy zyjlOWI50FIz(E+BI$`qxVe>v=^B!Syjj;JEVRMzRxkA`<2%AfU&BZV_XC0bx&Bf>4 zpCX&^c}A(GC?@4!ru?@l|1FDR(tZ}Ghk2U&O~TC$YcYh+8r8-3JbYFg_^f#NG}3Uf z$-U3|xCFj)=K|#7ZRooQilnKK%6Oc8dfCf|?X#e{Jl zFeX7gEST2`Ur85NRePUyfN;~@=~Q;ndw)C;L1y1SR1^Di&UG>4;v z7Z38X?P=!`?5XDNiDFgO#C10pnsUw7v0JO-+DKR2TyudfiOty6*}qY@h@B`Yh$jp! zk1kAIV!wpeL;I~@SwiD?hdX`@`8S?O(s?YU45ST0@C(Gdo?x$SvIEzAsw?VTf>Wt5oGKT-DkGK8ma|CZ#>ZJXI5hg{m}f2K zOGu663%S#SscdfOz|5e803WSIF<#ke}i|yU>^k(+}jAZSf0u zkdujic+gGC9dzceH}}E0xz}*KJSn~p$>AQu6xO%lp+tz(mRo9529`qra^)!fr|^hp zt2AwZ?X7b2u+=&`19_W^N2V)+=cphNvhxgI3&}i(o)-CNi~Mnm{0Y3+X+Qp8i~Z{s z8QH@4=Y@$cOW9&-AS4|9kcE?{M_Ith!Q#pM(0CE0q0dJ1*~0KUg^3e|^66r4VF0;- zvEoGCLYmSLq8q{u(0Z?LbfB)IvwOp(_U#@9BE+YOckJ-q*A805BcGpDJU+{O zC%p^4eBb8>srL?Q?lAGl7Q(vl^gI`ie^q$#dujb01m;t!XXlx1CI4a7yO&ozx$Mgi de7_B!_qKUF&wMw%8@~Lb&zS^)T4zqn{SQ&XF)IK7 diff --git a/release/src-rt/bcmcrypto/prebuilt/bn.o b/release/src-rt/bcmcrypto/prebuilt/bn.o deleted file mode 100644 index 414655d33d36fea0384cc834ef2433a9050afe37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 55964 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 UsbQ6dvos8ASgRrb7?92X1Mt0cU;qFB diff --git a/release/src-rt/bcmcrypto/prebuilt/dh.o b/release/src-rt/bcmcrypto/prebuilt/dh.o deleted file mode 100644 index 3134cd9c9cb0ac51cb729803b6780a0ed3319a20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 4216 zcwUuOO>7fK6#l&4I3`YD32y7s0K367u1YNnQZ=-ptP*}wiPET|679u5u}PvPj^!8; zPW2&&9HKatdI%DSh#m?RifIZ6RiH#bQ4YOU$^i-YQgNu%_J&j>_r0Cjc)d>gGt&6^ z{mlEHH~Ynj(7R`MgIg>bzDTrL@rRia-j8?g$4xL)={_ZmGWnR_tHeBi_^^H`>yU$e1Vz2DV~ zm2wYmmAmnMIfmu(L3~$^;AUCJy|QIzp$KDs5!;^A`I%K1MH3;ILE@LH)tzA#W;@GS zeBD%-Uc=FV8=7v>$Zm=3mdI|2?3T!GiR@C06|af=T@Iaa>(J0O$F!%_ie@abKl|sJ zkO*=HgXo;|pf46AA4MKI=d3t%T`?j>#fX`7{%SdduPMGGU92-m@%~gbHQSD%7ZuA^ zBw_jbxC+gfF|8c14I?Cc@{)}ZI+uPWKKmr>9hhUEt@AM`ccfnCKOs5x)mejes)0^5 z=%BoZ$PdlV`wZosYR`2hJwjiR>uLK)@x(a4DZ~zC_F!s8v4~a_HPL5K=q%Oi_NMjXSlQ-)t7gsU4+H7QcJze^yB^1Wc<1JvrXL8sd9*^EAKVuz&L{qUab2S3&4Bo?U-Z_B<&C>#0h;rIB*~9A2{PVEe%Qb?(Wc>@$j?B5i$R(Xr91OnX2&xlbGW(^P(x_I{vq zoSRx6!`2gUk*?w|gt5D}Q zqjzjU*SDaDx1b-~g5J6XUE6{l+JY|n2@1t*-ABF`I;ykg<*9EB)H_Pu9)F{t5P z)KjdJXAQptL8NW~i5n_yKkZi98to3+I_)s+2rQ z!G>8h&vU;h-+;xsSdEBYyFb*AHc#Y5S+a4J{?mL??D@cRK-6l5>bSfy!`L@5zknCb z$CmLw)*jmXHn4rg7u9Oj#>@u3xA@$_k2LU))$s=!_?|lbdIKMI=NtLWb?58spX%>_ zSC5=J^T``}cl1z{z89jCm&Oap6v0AXz!CdjJ~I|AWTpy;rjvyvqN&MACJv8g&rb+$ zE}choJe^5h7>*`WqlXV6Iy5mpp2-&QpBMYZ-!eXlo3yp&8efy}HQL)8=Mvk23LOl{ z^D1rn48j44d!^iHofx2(95t6I83Oi?@Szq*AL{iD_))iP-k|&+bI7&3 zpabU|?Q!57=UXnE>%z9CJ)CC`&bs(<7e4O7r(F273;)uEUvc3#T=*Rq{+RYNkMNQG z``N{RO8Yd`b4n5X-(CE_T)5&$DdR0Jyq)kzRF<&J$8HyYp9_x>{*1~p10ny8i~m01 zIiHA|`6pd`q(`Dd^b=2IOj5rzw@Y zP{_nT&s-usEY^SaTs)h($bW~%GRb`Wd_I%08JTR_{_7-97LxgbjSOe3zaM^d=B!g$ zDtjn3nyuqZl4QLPmf$E!W|=XZ$!7A&8Yg>UoVbNa>%Y*NPYRDLZ|H~xZPzvo*<3y} zo*WyS7-DQRJ8F4KZisw{)zl*Hwy#CJ8G(R!n*yz(mzX~y`SVPt`Foe)4q%NT6=$6x zU7}W=%QS>K81AC^!H_Q6IfC1$?{Wlvinv38mw;7ProAF9ZQzezw{!X60+8PbC{BJrYx3liRBs8c*rj_-+;k0zm? z$5)_J+z+M~e1iTJ(+!#pK9R3ApNM~*VOZ2xQN*``(k9+ml+Xoy|FxF$UFxt?9T046kSPrR`CI9_DJE1cBYA&mH{joVQhrd;G|Ct1I_zE z{{RAAbk4|NGsOLBuvq7F^eE|*KCY{gpsz+JZtLNqtvmUPzBJxb&gUiIZRsio`)FT& zh(sU5d>3iued|RB!@I5zShMf8a|BV%P4{um^{8A+WS8<+eD(1VTKQ0`k175;CuwT9 zZ0kymUKYJMIcN?B&B35K7&Hfi=3vkq44Q*Mb1-NQMiVOjRkmaI)WOz5^)*OuCh476 z2_5!ODuU}TEhq}wyAEKj<4CiL`<7+7Y?VH=bA;zP866tB77UNxy>~I#qjhWay=jHH ztR9OK>az}}-Q8?zTGLZcb!f?$9)lJy6u3B*$vvKNy!qrTv}`gJe=?=T;+ZSm&=ND* zY$~T8SzMj*y7<2k5Ijmt@m2kbz%#U(rE^g_ut3-f=X?XLCR!H+_lvkODHk_4-z5?M zzqknO+VZZO$8}0^{9ev)05$(~n&N_!15ccb@>K^7j(8kS-JB|7FXuaGbZT}@u3a`+Z@@1LlKDNS{53al z-T>MB_DjjU(Zd6f%}-UkClvdgnEfuU@%?Fu^FCD%4|(`y5AXMIq_eSvmat(Wo9xBJ zRDL3vDddq&WeX`C@x)Ai4tIuoZ{;#N$9sAD-%@-xlF7xUMXtsc=j{W8Xc(A(^3m09ua1n~oLAr2N(ym-cr{8_|PV#1^e-|F- zou7N|_nmX@d!L;=-6w=VZ3(ntO9Q%Ff#+-tbO%}jJFy-0>&2tM*KxOUC6cMG#TRhT zpT~+nhnxPFxZ%%Y*|+h%AH{MUxFX%T5?lwCJL{qSsS|M*%Aj8czC_w`Q;rqb8MA43 zGTN5VHl87QhU6KNXGoqQ+fa#kSc`}8%>B6*pAh%_G4X>xBJTJZaofKjZu#fMs()6j z_ygjme_Gt|`-R4M42uc3nq@kxx?t~;rrqR4EG4wU9@>ms~vj< zF2__3U9-|w&V<@uvYIiJiLD%IjxU+Idz-fA82o)s+T4T}*qu7NXE>Ft2r7G&ooyxF z$KSCpl6{fvi)3FU`y$yF$-YSTMY1oFeF^$n5NknQRsEYWg=!bFN3j&&a z13MO;5t}pngfsgq?)Vkl_8;Mv&vX2ToZ$zY;h#9e_c_B+&PNOJsN7}ShJ(ec?p@Bw zGUvr9;{?8myQvC#;av^RoUMR+WG`+8*e&euauX*lhqx@(NX6`9AA39OATG)oYr&x| z@C<>oF@cWQE1Wa67dZ2+>r_snYFpjv#+r>ORSA&YV(l$1s=y- z`wTuuZ^HFhn^FbtHIHA7w5@9NGAf-4r^A}K3xMjK(jQ<+&l>OkIu@nEYGaYTSPXb| z^4;yZXocrY)j`D(mn1GpT#~pXaY^Em#3fxDP<+bd6P%eacQ2)TLk!k0oC!BEVEtR3 zYSoI>@;pQJ5B%fWU3yxrR%@Ea=OsS-HvQG|vyi_an*4S9H=6dpUFR={{ilu}f73~v zdhgt;PIvNPlHcp(%%yxWJ49KW)^e=&Hl3SD7IU8zksQeuvq%oj%qZjN_~b`Z+FKZz zMlwH=8~S)OnH?H`;~6)J7qxWnvM zTiW>SH+saxrM97N)$$!M@&6TfP1ob?g@K@9vZj8XPftM zz6lyGhV(G@@Cw^o@Ou@Z6=~QNsXIaGp}`3Bwg$bvNRiE{s_E_6ZQkdg>Ljo?6ZgWd<7D`x3@?>G3vHCFl{pH;^4;~m83sjrh})aV$?XNL!8#~ikmla>f5t}1+|5i2_;D~ZRBO4^UMpK=em(U z3Y~A=_@5ZN8aySVmiCWX+W)Ds&l|g{pTcq1GB_-KUM!+zM#){ktkG3{Rs5rfj!(51 boJMAp?9g?v+Vy?3cIj`C)uH)Yyi|Vy^dJyH diff --git a/release/src-rt/bcmcrypto/prebuilt/md5.o b/release/src-rt/bcmcrypto/prebuilt/md5.o deleted file mode 100644 index bad9a57d3334eb7c9bb42851dbe6fa59ef596668..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 5564 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 K`89G)Hva?qiwZ9Q diff --git a/release/src-rt/bcmcrypto/prebuilt/passhash.o b/release/src-rt/bcmcrypto/prebuilt/passhash.o deleted file mode 100644 index 196a34ecb4949af01a250c97512d418fb053aa5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 3124 zcwUuOO=uKn7=C6Zi9hjYv|F3D+Rn6Vc8y_KZCX;XbV#B`2qlLIDM+)~>^2GHXU(pl zmv#vra*)hYJVfxYL<$~cHzxiaw1%E~2*qQM!IK9sEiIK+I(^>xNoH51_JiS@_j`Z7 z_j%s;`)0m9(RWf&6a+)TR%}YZl`X&)9sM1y6vs|%NA1{u9Jm%U*RN{p&cj#>9#wTb zs75e*SwmO65te=kKgJzLjZ$ZC#kywTVeD_m(t)e?w&#Y{f=f~Q*nc|EO}#c|i7_V_ za|}OJGq_hx;coRT?o)f7N?QYpE>`un)-PtdRP1??V+nt3x)XuD8JK#nR#;#FmN~4fu)$_ zYZ@svf=1?hw`wMfs^o8WS}OOZZe2CwtLignwgg-+Dfm9x$~`HU|8kZh3itM6tkO>6 zG)2W`!l)x@J2TxjMtA;ML}0I@;_op?Sfc+fW}rcX{f@X`0K2*`1?F*!jr5E zSB`V1RWK@y>T^{IYWJOEMWl8mANT9xl)embhWoC_zPrG_E3oHstn~zYZj3#bVb7)5 zb7$FegMQDMcoH|TC)zys#Kqcy<(PTD2(w%UF~E#ls$jgr{YuP3@GLMV!C+t|X6on2 zmG1Gx&eGa+yh)z+k*BxNUyhKs1{`cP4T-}Z>n!?Qt%SHrxxE)~rDCz|0IZ1U73S7k z*T1!KmP2tYHO#r!*V3<+3e@&B<&C}$dRStRH=DfKb1Q@?nspIXx54mq0M~gC!%{c7CWt(x>lagP`%`fTZmu~;V zzpG6H#0)py0DHr7d0~IF0DVv^9;a%>!k$VG_Ew(qEcW7!O89H>0?u!E^(a1f948PA zJ_q=`zoB+kUxf6zkbX^d^)>#*m;67k(f7Wj-(90mhV`eqyN?<1Q(v4pWOO8sCip!} zZ2J6YVmLki z(NQEurY9$}Qw6;Cki6tu-Q>#_pJX6#=>GgJpKT$(j%MH&&YWET21q{w2Yp%d?Q)@5 zGJ<%Aef$5i6aJ{msUf?Tke%!+@@GKJKgS&H%5`=!K1D5#9XsTY#KX~qO&ndQjThg7 zni1&w{r6 zxZ8Z&3#w=TNuA!3hiS$YPk*{jFZCK@S`XmqzpB$CH=NIp4d=%aBRGlCY+)!^z|d%J zC^MeVAw4pkyNJy6rfO_*cw~sLM>gESV?2?a!uZs9D8yuTGN0WzosG?2J)1c5Vn*{0 z51XtH`s>eReV5k*qW|5W`4Mr~2USm&8i?Ox)$`LeZ@o|R>@NB8O8MxyLa!ZJH2|S^h?RS+q+Ly7WQA! CNK@

fS42T)42{VkjscWsK*giJS5ypB4t5h3wog`wru~?0g1xrU-j9 zi(ip2ZL5GwCQO$KI@}qn~*Q9V0D?(vN#ZmaN2`SotB1?J)W7_sGR>Ia-rDRaqCYZ*D z&KKp{2wzIpSSt81R;deOQ;2E_9V@|n2b)8yt*KOEp>j>-*~5Pe;U(j?Tr_UUe~fwg z)R>b`j9K~En30c+X<0O;jBSLz?- z=wY_P2kDgEGAvtGg%9eDpxy}TjiBBL>W!e@2?Z+;%(B|9nGhONkKqj)s4d1hcsV-b0(E0MLw zXl6&@;LoI-Y>WC3Q8;w_wy!|(T4`78pL3IkM zQ&63P>ZCnf-V=A>?Fn~}(XP-rO;XG$_8YyW%4sz|y*brB%d}*ap5cX5DlC;sB~Loa zf!B%ee8D-`vh&QM@BA)&=Lg%`KCmJOKmGD8D<0h&rQh@D$l0NES2ywWu;zo_x8c5% z(RAN8X+(Rw(p`vlkBlhgz=>1+r}b&7cNo#3-oEZL1JSPT6YuRswCD8DP~WLER!u4| z^NAj@_Pa8?~yAnxja~-^_?~P{>d7xzu@Xs4^;e#8XZ4atNjluPK~?g R%8D3)-BR4t`-u@y{s$s{loS8} diff --git a/release/src-rt/bcmcrypto/prebuilt/random.o b/release/src-rt/bcmcrypto/prebuilt/random.o deleted file mode 100644 index 1bc782ef722eff782ffb5d95c9f89a8635677656..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 2444 zcwUuOL2nyH6#jPCaqXlfCJm65B5br!Bk0;mEKm!TLfy0l1=p$)2}Gss+TJ9F*lX=> zP$MdlLl7WEb&+~#r5<{KD=vjf9E#uvaNsB81_va9#GwZy^PXp1kC#+}k!Ig~Z@%}< z+c&dge>}f%M$eUkc?y4`nfq{TOaXUI%U+&FtJXe(C;jG>acQCcf>Y zakp~>-*l#Mr<20{4)8_0+tp1Ve>HPs6DOcgWUk#tW|K8;wgK~MCVNRwK1dsx{G3iP z#5YV0sTU5RILREI6KfW?W6;gRs7x|%l*WH_^(TeS7WGf4f7)hD`LrpYHs#Z%eA<)` zb109msQ+rdhq#$Q+Q_4q`@gse?DXdTukMnfD`I=Onfwl$7%@5TpSopwujjswYO6ZT zf19-Kb&=v2wcgC-HKO}4@NZEKyIpm+{>J!SJhF{%K2Z31>d#Pr_R#_Vc|KQjKg_NB zPP67U*iX3cGbhu>rjc9q8g6dct$F?jxzKAkp_lXBHP;E;T;Nxa`C+b7ZB+e@ z7Eknottx2+p%bnLQiNKahtv7q`fK&(`el2tF3uKgteO)#uqr{o&Xsy|*%Py^nh&c{b1UmBmQ$(E&XC( zlKehzSG^Dv9#@!hYv~GaO5yRkj86hXcS?c+E=73Uj$`;e!la1j_lRTg9;Yy@x2j{P z_2$aSUq5O()Qb@cLFw{pS(j4mlr# z(B=GiZLW!`cV!=NPr;Gx+0!4xpF{V65s5N}R$v^1+KgW1Rh-1A9E&;{y>FeHICuTo zK7SOikX?J|N#ZqnnhKty=S2n2Lv2aC1$AH4lfwEV5gdow42$0B?3I>Xs|PLku2Um1*Y}&Az2;S&uE=zXoDLQLplXN&=X8!?kM{<5;P3WHHdHVPk*-!SICUoDCx(k}ny(o2g ouelDPChBm7btc4~vwvIque1L!y*J0p3qvQHW;-SBb^Q?V52-aaM*si- diff --git a/release/src-rt/bcmcrypto/prebuilt/rc4.o b/release/src-rt/bcmcrypto/prebuilt/rc4.o deleted file mode 100644 index 083312bbf68556e17cfdb8164e33070af914513e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 1224 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

  • O%0>nK2}a0V+;5@#E#~P+byz?je51y{HEUQp2BF;#NSo+0C^dBj%TPAoM7 z*Wu?x35H_vD^g>kfGUN)mX9H|uF2 ztwKqm6}sb>ZQy=u%t^b4sC_rvK0blD!Q(^JHWvOy0o_3;HPOG4tb%Y0>ul?oi*Bzk zCM(}d>rJf@{%u);u|m-Mkn@+2^A}$z=fs5DfDT4kwofJqGFBV5ClhOK*R>$l3@*w# zZKi~(c}#^PdmipNHgDr+5&(UPvGzbsJuoB$ zTTiv8J892Hr`U61Vx^gdHM32nZKd5@I@>js78E%4gI)1_(zZO_Pca|cQS(AC&@t;5 zajMv;%UQpb(CrAv7r3{AZxyOEsX~EXIxt6j)bX2UwA-Z)S$}6Zj-m58!$r~$XL&AC(dT}c?)agvU2*zW_QQgZ7wMuDp($ls;Mf*58{;s` z%45K1M^Z5M<%u?lwR#F7)Sj<-W=We?;-2j_lb%N{`@&6UcsR@;LreYXfJRm3LNSK4)sprP;VUduuUZriv|h)S;cWA{QHS( z;#2w?elziR{eR;9A7yL8`s2jJ#N<0${O7-Se(CmSQ@;29)%(Bx{cZ2_?5Xnk{)6{} zf5ZE`g161CpVvUw{s!he5!lmw*I~2aP|Lq4#j}076 zzaZ}0UT}J6o&LhtvhVJ`|Mb?s9RIm}IPIOMyDvZe{PXLde*c?`PXEi<|M7g@`G3mR zH`jbP`{<7DCGQ*=U;V#&|Mcj}6}Jp*JX<$>uF5t3(%0|({-;^*o?W!(@Y^doUP)V5 zU0t*@^Sf1z+I6*`ZLGPYFsJdZRogPx{B!2RkJi4N_{Pqft^NOW@%#IiuAMR5_2kmT zffXBGD!JJIhMxA+k9W??{ax4K!)o#KLnZDFHRdyUcU#wNsO?_U(@nLV4|P98we8!s@xyiNH?7_5 zyzT1TO0^q1*R+3SUF}2d>*v+qK`Bl||*}9Y|{XA3p@x0u=nds{O&j%k`Qy!!wuk-2ZbzH)O7IM~+MpxDm zpsU9V*3nhJ$#*Tu`}!&U+*A6cB;R+?)p}{EyCTzMKmI*P*Xa2sXFQfKldj0Ojhyi& z_0op%)F}c_>hG(`e!gV83xXD0=_cRtAOA~$N!j=pM!y}`^qag+&dI;=c|>vH%*SJ} ze0w!T%9j4izjE15p_=4~JCZjKwgZwLp{1NV)@O1*Kg~(YNQ84o40j8xOr>mnyr(aZ(qL& zn0HktM!%~&t=js~rfq9CZ{0Zg;O;JTT9a%gWte>T=$ftD)^Fa#>tbI?Ed;N?H4WFI z9QZQ+O7WML+{@J9NqK#caraeRnGUzs+{i!am_*n*;4I1Z}B?U zRSTLgvfY<#_a@tWlWq11mUE=qk@Gv% z&N`m0cGhtw`Tkt;{p+}96+6Dd&)-cx_s(+UX`SV~XW!xXp<3ttAg);eoN>Ow>CW+W z8uW{62An7bzLl2Z_!xheJ;(X38P_a0_^LV1cN^w7-wn=jz8g+{$3G?CiBYA%$ss6; msEx0X%jWAehubKSFV0thz`K0qAVBOZCHS7NGm_(F5&d5xyarbQ diff --git a/release/src-rt/bcmcrypto/prf.c b/release/src-rt/bcmcrypto/prf.c new file mode 100755 index 0000000000..90c265d44d --- /dev/null +++ b/release/src-rt/bcmcrypto/prf.c @@ -0,0 +1,353 @@ +/* + * prf.c + * Pseudo-ranom function used by WPA and TGi + * + * Original implementation of hmac_sha1(), PRF(), and test vectors data are + * from "SSN for 802.11-0.21.doc" + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: prf.c,v 1.18 2006-06-15 02:17:55 Exp $ + */ + +#include +#include +#include + + + +#ifdef BCMDRIVER +#include +#else +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, int len); +extern int bcmp(const void *b1, const void *b2, int len); +extern void bzero(void *b, int len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif /* __GNUC__ */ +#endif /* BCMDRIVER */ + +void +BCMROMFN(hmac_sha1)(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest) +{ + SHA1Context icontext, ocontext; + uint32 pki[(PRF_MAX_KEY_LEN / sizeof(uint32)) + 1]; + uint32 pko[(PRF_MAX_KEY_LEN / sizeof(uint32)) + 1]; + uint8 *k_ipad = (uint8 *)pki; + uint8 *k_opad = (uint8 *)pko; + int i; + + /* if key is longer than 64 bytes reset it to key = SHA1(key) */ + if (key_len > 64) { + SHA1Context tctx; + SHA1Reset(&tctx); + SHA1Input(&tctx, key, key_len); + SHA1Result(&tctx, key); + key_len = 20; + } + + /* + * the HMAC_SHA1 transform looks like: + * + * SHA1(K XOR opad, SHA1(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + bcopy(key, k_ipad, key_len); + bzero(&k_ipad[key_len], PRF_MAX_KEY_LEN + 1 - key_len); + bcopy(k_ipad, k_opad, PRF_MAX_KEY_LEN + 1); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 16; i++) { + pki[i] ^= 0x36363636; + pko[i] ^= 0x5c5c5c5c; + } + /* init contexts */ + SHA1Reset(&icontext); + bcopy(&icontext, &ocontext, sizeof(icontext)); + + /* perform inner SHA1 */ + SHA1Input(&icontext, k_ipad, 64); /* start with inner pad */ + SHA1Input(&icontext, text, text_len); /* then text of datagram */ + SHA1Result(&icontext, digest); /* finish up 1st pass */ + + /* perform outer SHA1 */ + SHA1Input(&ocontext, k_opad, 64); /* start with outer pad */ + SHA1Input(&ocontext, digest, 20); /* then results of 1st hash */ + SHA1Result(&ocontext, digest); /* finish up 2nd pass */ +} + +/* PRF + * Length of output is in octets rather than bits + * since length is always a multiple of 8 + * output array is organized so first N octets starting from 0 + * contains PRF output + * + * supported inputs are 16, 32, 48, 64 + * output array must be 80 octets in size to allow for sha1 overflow + */ +int +BCMROMFN(PRF)(unsigned char *key, int key_len, unsigned char *prefix, + int prefix_len, unsigned char *data, int data_len, + unsigned char *output, int len) +{ + int i; + unsigned char input[PRF_MAX_I_D_LEN]; /* concatenated input */ + int currentindex = 0; + int total_len; + int data_offset = 0; + + if ((prefix_len + data_len + 1) > PRF_MAX_I_D_LEN) + return (-1); + + if (prefix_len != 0) { + bcopy(prefix, input, prefix_len); + input[prefix_len] = 0; /* single octet 0 */ + data_offset = prefix_len + 1; + } + bcopy(data, &input[data_offset], data_len); + total_len = data_offset + data_len; + input[total_len] = 0; /* single octet count, starts at 0 */ + total_len++; + for (i = 0; i < (len + 19) / 20; i++) { + hmac_sha1(input, total_len, key, key_len, &output[currentindex]); + currentindex += 20; /* next concatenation location */ + input[total_len-1]++; /* increment octet count */ + } + return (0); +} + + +/* faster PRF, inline hmac_sha1 functionality and eliminate redundant + * initilizations + */ +int +BCMROMFN(fPRF)(unsigned char *key, int key_len, unsigned char *prefix, + int prefix_len, unsigned char *data, int data_len, + unsigned char *output, int len) +{ + uint32 pki32[(PRF_MAX_KEY_LEN / sizeof(uint32)) + 1]; + uint32 pko32[(PRF_MAX_KEY_LEN / sizeof(uint32)) + 1]; + uint8 *pki8 = (uint8 *)pki32; + uint8 *pko8 = (uint8 *)pko32; + + SHA1Context reficontext, refocontext, icontext, ocontext; + int i, total_len, currentindex = 0; + uint8 input[PRF_MAX_I_D_LEN]; + int data_offset = 0; + + if ((prefix_len + data_len + 1) > PRF_MAX_I_D_LEN) + return (-1); + + if (prefix_len != 0) { + bcopy(prefix, input, prefix_len); + input[prefix_len] = 0; + data_offset = prefix_len + 1; + } + bcopy(data, &input[data_offset], data_len); + total_len = data_offset + data_len; + input[total_len] = 0; + total_len++; + + /* if key is longer than 64 bytes reset it to key = SHA1(key) */ + if (key_len > PRF_MAX_KEY_LEN) { + SHA1Context tctx; + SHA1Reset(&tctx); + SHA1Input(&tctx, key, key_len); + SHA1Result(&tctx, key); + key_len = SHA1HashSize; + } + + /* store key in pads */ + bcopy(key, pki8, key_len); + bzero(&pki8[key_len], PRF_MAX_KEY_LEN + 1 - key_len); + bcopy(pki8, pko8, PRF_MAX_KEY_LEN + 1); + + /* XOR key with ipad and opad values */ + for (i = 0; i < PRF_MAX_KEY_LEN / 4; i++) { + pki32[i] ^= 0x36363636; + pko32[i] ^= 0x5c5c5c5c; + } + + /* init reference contexts */ + SHA1Reset(&reficontext); + bcopy(&reficontext, &refocontext, sizeof(reficontext)); + SHA1Input(&reficontext, pki8, PRF_MAX_KEY_LEN); + SHA1Input(&refocontext, pko8, PRF_MAX_KEY_LEN); + + for (i = 0; i < (len + SHA1HashSize - 1) / SHA1HashSize; i++) { + /* copy reference context to working copies */ + bcopy(&reficontext, &icontext, sizeof(reficontext)); + bcopy(&refocontext, &ocontext, sizeof(refocontext)); + + /* perform inner SHA1 */ + SHA1Input(&icontext, input, total_len); + SHA1Result(&icontext, &output[currentindex]); + + /* perform outer SHA1 */ + SHA1Input(&ocontext, &output[currentindex], SHA1HashSize); + SHA1Result(&ocontext, &output[currentindex]); + + currentindex += SHA1HashSize; + input[total_len-1]++; + } + + return (0); +} + +#ifdef BCMPRF_TEST +#include +#include "prf_vectors.h" + +#ifdef PRF_TIMING +#include +#include +#endif /* PRF_TIMING */ + +void dprintf(char *label, uint8 *data, int dlen, int status) +{ + int j; + printf("%s:\n\t", label); + for (j = 0; j < dlen; j++) { + printf("%02x ", data[j]); + if ((j < dlen - 1) && !((j + 1) % 16)) + printf("\n\t"); + } + printf("\n\t%s\n\n", !status?"Pass":"Fail"); +} + +#ifdef PRF_TIMING +#define NITER 10000 + +int main(int argc, char* argv[]) +{ + struct timeval tstart, tend; + unsigned char output[64 + 20]; + int32 usec; + int j; + + bzero(output, 64); + if (gettimeofday(&tstart, NULL)) exit(1); + for (j = 0; j < NITER; j++) { + fPRF(prf_vec[0].key, prf_vec[0].key_len, (unsigned char *)"prefix", + 6, prf_vec[0].data, prf_vec[0].data_len, output, 64); + } + if (gettimeofday(&tend, NULL)) exit(1); + dprintf("fPRF", output, 64, 0); + usec = tend.tv_usec - tstart.tv_usec; + usec += 1000000 * (tend.tv_sec - tstart.tv_sec); + printf("usec %d\n", usec); + + bzero(output, 64); + if (gettimeofday(&tstart, NULL)) exit(1); + for (j = 0; j < NITER; j++) { + PRF(prf_vec[0].key, prf_vec[0].key_len, (unsigned char *)"prefix", + 6, prf_vec[0].data, prf_vec[0].data_len, output, 64); + } + if (gettimeofday(&tend, NULL)) exit(1); + dprintf("PRF", output, 64, 0); + usec = tend.tv_usec - tstart.tv_usec; + usec += 1000000 * (tend.tv_sec - tstart.tv_sec); + printf("usec %d\n", usec); + + bzero(output, 64); + if (gettimeofday(&tstart, NULL)) exit(1); + for (j = 0; j < NITER; j++) { + fPRF(prf_vec[0].key, prf_vec[0].key_len, (unsigned char *)"prefix", + 6, prf_vec[0].data, prf_vec[0].data_len, output, 64); + } + if (gettimeofday(&tend, NULL)) exit(1); + dprintf("fPRF", output, 64, 0); + usec = tend.tv_usec - tstart.tv_usec; + usec += 1000000 * (tend.tv_sec - tstart.tv_sec); + printf("usec %d\n", usec); + + bzero(output, 64); + if (gettimeofday(&tstart, NULL)) exit(1); + for (j = 0; j < NITER; j++) { + PRF(prf_vec[0].key, prf_vec[0].key_len, (unsigned char *)"prefix", + 6, prf_vec[0].data, prf_vec[0].data_len, output, 64); + } + if (gettimeofday(&tend, NULL)) exit(1); + dprintf("PRF", output, 64, 0); + usec = tend.tv_usec - tstart.tv_usec; + usec += 1000000 * (tend.tv_sec - tstart.tv_sec); + printf("usec %d\n", usec); + + return (0); +} + +#else + +int main(int argc, char* argv[]) +{ + unsigned char digest[20]; + unsigned char output[64 + 20]; + int k, c, fail = 0; + + for (k = 0; k < NUM_VECTORS; k++) { + printf("Test Vector %d:\n", k); + hmac_sha1(prf_vec[k].data, prf_vec[k].data_len, prf_vec[k].key, + prf_vec[k].key_len, digest); + c = bcmp(digest, prf_vec[k].digest1, 20); + dprintf("HMAC_SHA1", digest, 20, c); + if (c) fail++; + + bzero(output, 64); + if (PRF(prf_vec[k].key, prf_vec[k].key_len, + prf_vec[k].prefix, prf_vec[k].prefix_len, + prf_vec[k].data, prf_vec[k].data_len, output, 16)) + fail++; + c = bcmp(output, prf_vec[k].prf, 16); + dprintf("PRF", output, 16, c); + if (c) fail++; + + bzero(output, 64); + if (fPRF(prf_vec[k].key, prf_vec[k].key_len, + prf_vec[k].prefix, prf_vec[k].prefix_len, + prf_vec[k].data, prf_vec[k].data_len, output, 16)) + fail++; + c = bcmp(output, prf_vec[k].prf, 16); + dprintf("fPRF", output, 16, c); + if (c) fail++; + + bzero(output, 64); + if (PRF(prf_vec[k].key, prf_vec[k].key_len, + prf_vec[k].prefix, prf_vec[k].prefix_len, + prf_vec[k].data, prf_vec[k].data_len, output, 64)) + fail++; + c = bcmp(output, prf_vec[k].prf, 64); + dprintf("PRF", output, 64, c); + if (c) fail++; + + bzero(output, 64); + if (fPRF(prf_vec[k].key, prf_vec[k].key_len, + prf_vec[k].prefix, prf_vec[k].prefix_len, + prf_vec[k].data, prf_vec[k].data_len, output, 64)) + fail++; + c = bcmp(output, prf_vec[k].prf, 64); + dprintf("fPRF", output, 64, c); + if (c) fail++; + } + + + fprintf(stderr, "%s: %s\n", *argv, fail?"FAILED":"PASSED"); + return (fail); +} +#endif /* PRF_TIMING */ +#endif /* BCMPRF_TEST */ diff --git a/release/src-rt/bcmcrypto/prf_vectors.h b/release/src-rt/bcmcrypto/prf_vectors.h new file mode 100755 index 0000000000..77419b191d --- /dev/null +++ b/release/src-rt/bcmcrypto/prf_vectors.h @@ -0,0 +1,143 @@ +/* + * prf_vectors.h + * PRF test vectors + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: prf_vectors.h,v 1.7 2006-06-22 00:16:57 Exp $ + */ + +#include + +/* test vectors from rfc2202 */ +uint8 key_0[] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }; + +uint8 prefix_0[6] = "prefix"; + +uint8 data_0[8] = "Hi There"; + +uint8 digest_0[] = { + 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d + }; + +uint8 digest1_0[] = { + 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00 + }; + +uint8 prf_0[] = { + 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84, + 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54, + 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06, + 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee, + 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88, + 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb, + 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e, + 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a + }; + + +uint8 key_1[4] = "Jefe"; + +uint8 prefix_1[6] = "prefix"; + +uint8 data_1[28] = "what do ya want for nothing?"; + +uint8 digest_1[] = { + 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 + }; + +uint8 digest1_1[] = { + 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, + 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, + 0x25, 0x9a, 0x7c, 0x79 + }; + +uint8 prf_1[] = { + 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad, + 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4, + 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58, + 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09, + 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa, + 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02, + 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7, + 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc + }; + + +uint8 key_2[] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA + }; + +uint8 prefix_2[6] = "prefix"; + +uint8 data_2[] = { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD + }; + +uint8 digest_2[] = { + 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 + }; + +uint8 digest1_2[] = { + 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, + 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, + 0x63, 0xf1, 0x75, 0xd3 + }; + +uint8 prf_2[] = { + 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f, + 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1, + 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1, + 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce, + 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc, + 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae, + 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6, + 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07 + }; + +typedef struct { + unsigned char *key; + int key_len; + unsigned char *prefix; + int prefix_len; + unsigned char *data; + int data_len; + unsigned char* digest; + unsigned char* digest1; + unsigned char* prf; +} prf_vector_t; + +#define PRF_VECTOR_ENTRY(x) \ +{ \ + key_##x, sizeof(key_##x), prefix_##x, sizeof(prefix_##x), \ + data_##x, sizeof(data_##x), digest_##x, digest1_##x, prf_##x \ +} + +prf_vector_t prf_vec[] = { + PRF_VECTOR_ENTRY(0), + PRF_VECTOR_ENTRY(1), + PRF_VECTOR_ENTRY(2) +}; + +#define NUM_VECTORS (sizeof(prf_vec)/sizeof(prf_vec[0])) diff --git a/release/src-rt/bcmcrypto/random.c b/release/src-rt/bcmcrypto/random.c new file mode 100755 index 0000000000..dfa9a4d295 --- /dev/null +++ b/release/src-rt/bcmcrypto/random.c @@ -0,0 +1,180 @@ +/* + * random.c + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: random.c,v 1.13 2009-06-11 02:38:23 Exp $ + */ +#include +#if defined(__linux__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) +#include +#elif WIN32 +#include +#include +#include +#endif /* __linux__ */ + +#include +#include +#include + +#if defined(__linux__) +void linux_random(uint8 *rand, int len); +#elif WIN32 +void windows_random(uint8 *rand, int len); +#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) +void generic_random(uint8* rand, int len); +#endif /* __linux__ */ + +void RAND_bytes(unsigned char *buf, int num) +{ +#if defined(__linux__) + linux_random(buf, num); +#elif WIN32 + windows_random(buf, num); +#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) + generic_random(buf, num); +#endif /* __linux__ */ +} + +#if defined(__linux__) +void RAND_linux_init() +{ + BN_register_RAND(linux_random); +} + +#ifndef RANDOM_READ_TRY_MAX +#define RANDOM_READ_TRY_MAX 10 +#endif + +void linux_random(uint8 *rand, int len) +{ + static int dev_random_fd = -1; + int status; + int i; + + if (dev_random_fd == -1) + dev_random_fd = open("/dev/urandom", O_RDONLY|O_NONBLOCK); + + assert(dev_random_fd != -1); + + for (i = 0; i < RANDOM_READ_TRY_MAX; i++) { + status = read(dev_random_fd, rand, len); + if (status == -1) { + if (errno == EINTR) + continue; + + assert(status != -1); + } + + return; + } + + assert(i != RANDOM_READ_TRY_MAX); +} +#elif __ECOS +void RAND_ecos_init() +{ + BN_register_RAND(generic_random); +} +#elif WIN32 +void RAND_windows_init() +{ + BN_register_RAND(windows_random); +} + +void windows_random(uint8 *rand, int len) +{ + /* Declare and initialize variables */ + + HCRYPTPROV hCryptProv = NULL; + LPCSTR UserName = "{56E9D11F-76B8-42fa-8645-76980E4E8648}"; + + /* + Attempt to acquire a context and a key + container. The context will use the default CSP + for the RSA_FULL provider type. DwFlags is set to 0 + to attempt to open an existing key container. + */ + if (CryptAcquireContext(&hCryptProv, + UserName, + NULL, + PROV_RSA_FULL, + 0)) + { + /* do nothing */ + } + else + { + /* + An error occurred in acquiring the context. This could mean + that the key container requested does not exist. In this case, + the function can be called again to attempt to create a new key + container. Error codes are defined in winerror.h. + */ + if (GetLastError() == NTE_BAD_KEYSET) + { + if (!CryptAcquireContext(&hCryptProv, + UserName, + NULL, + PROV_RSA_FULL, + CRYPT_NEWKEYSET)) + { + printf("Could not create a new key container.\n"); + } + } + else + { + printf("A cryptographic service handle could not be acquired.\n"); + } + } + + if (hCryptProv) + { + /* Generate a random initialization vector. */ + if (!CryptGenRandom(hCryptProv, len, rand)) + { + printf("Error during CryptGenRandom.\n"); + } + if (!CryptReleaseContext(hCryptProv, 0)) + printf("Failed CryptReleaseContext\n"); + } + return; +} +#elif TARGETOS_nucleus +void RAND_generic_init() +{ + BN_register_RAND(generic_random); +} +#endif /* __linux__ */ + +#if (defined(__ECOS) || defined(TARGETOS_nucleus)) +void +generic_random(uint8 * random, int len) +{ + int tlen = len; + while (tlen--) { + *random = (uint8)rand(); + *random++; + } + return; +} +#endif diff --git a/release/src-rt/bcmcrypto/rc4.c b/release/src-rt/bcmcrypto/rc4.c new file mode 100755 index 0000000000..30a838a1c1 --- /dev/null +++ b/release/src-rt/bcmcrypto/rc4.c @@ -0,0 +1,114 @@ +/* + * rc4.c + * RC4 stream cipher + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: rc4.c,v 1.10 2006-06-14 21:07:54 Exp $ + */ + +#include +#include + +void +BCMROMFN(prepare_key)(uint8 *key_data, int key_data_len, rc4_ks_t *ks) +{ + unsigned int counter, index1 = 0, index2 = 0; + uint8 key_byte, temp; + uint8 *key_state = ks->state; + + for (counter = 0; counter < RC4_STATE_NBYTES; counter++) { + key_state[counter] = (uint8) counter; + } + + for (counter = 0; counter < RC4_STATE_NBYTES; counter++) { + key_byte = key_data[index1]; + index2 = (key_byte + key_state[counter] + index2) % RC4_STATE_NBYTES; + temp = key_state[counter]; + key_state[counter] = key_state[index2]; + key_state[index2] = temp; + index1 = (index1 + 1) % key_data_len; + } + + ks->x = 0; + ks->y = 0; +} + +/* encrypt or decrypt using RC4 */ +void +BCMROMFN(rc4)(uint8 *buf, int data_len, rc4_ks_t *ks) +{ + uint8 tmp; + uint8 xor_ind, x = ks->x, y = ks->y, *key_state = ks->state; + int i; + + for (i = 0; i < data_len; i++) { + y += key_state[++x]; /* mod RC4_STATE_NBYTES */ + tmp = key_state[x]; + key_state[x] = key_state[y]; + key_state[y] = tmp; + xor_ind = key_state[x] + key_state[y]; + buf[i] ^= key_state[xor_ind]; + } + + ks->x = x; + ks->y = y; +} + +#ifdef BCMRC4_TEST +#include + +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, int len); +extern int bcmp(const void *b1, const void *b2, int len); +extern void bzero(void *b, int len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif + +#include "rc4_vectors.h" +#define NUM_VECTORS (sizeof(rc4_vec)/sizeof(rc4_vec[0])) + +int main(int argc, char **argv) +{ + int k, fail = 0; + uint8 data[RC4_STATE_NBYTES]; + rc4_ks_t ks; + for (k = 0; k < NUM_VECTORS; k++) { + bzero(data, RC4_STATE_NBYTES); + bcopy(rc4_vec[k].input, data, rc4_vec[k].il); + + prepare_key(rc4_vec[k].key, rc4_vec[k].kl, &ks); + rc4(data, rc4_vec[k].il, &ks); + if (bcmp(data, rc4_vec[k].ref, rc4_vec[k].il) != 0) { + printf("%s: rc4 encrypt failed\n", *argv); + fail++; + } else { + printf("%s: rc4 encrypt %d passed\n", *argv, k); + } + + bzero(data, RC4_STATE_NBYTES); + bcopy(rc4_vec[k].ref, data, rc4_vec[k].il); + + prepare_key(rc4_vec[k].key, rc4_vec[k].kl, &ks); + rc4(data, rc4_vec[k].il, &ks); + if (bcmp(data, rc4_vec[k].input, rc4_vec[k].il) != 0) { + printf("%s: rc4 decrypt failed\n", *argv); + fail++; + } else { + printf("%s: rc4 decrypt %d passed\n", *argv, k); + } + } + + printf("%s: %s\n", *argv, fail?"FAILED":"PASSED"); + return (fail); +} +#endif /* BCMRC4_TEST */ diff --git a/release/src-rt/bcmcrypto/rc4_vectors.h b/release/src-rt/bcmcrypto/rc4_vectors.h new file mode 100755 index 0000000000..c540396e6e --- /dev/null +++ b/release/src-rt/bcmcrypto/rc4_vectors.h @@ -0,0 +1,294 @@ +/* + * rc4_vectors.h + * RC4 stream cipher test vectors + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: rc4_vectors.h,v 1.3 2006-06-14 21:08:49 Exp $ + */ + +#include + +/* 16 byte key, 16 bytes of data */ +uint8 key_00[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_00[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_00[] = { + 0xE9, 0x8D, 0x62, 0xCA, 0x03, 0xB7, 0x7F, 0xBB, + 0x8E, 0x42, 0x3D, 0x7D, 0xC2, 0x00, 0xC4, 0xB0 + }; + +/* 24 byte key, 16 bytes of data */ +uint8 key_01[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + +uint8 input_01[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_01[] = { + 0x2A, 0x82, 0xD7, 0xBB, 0xCF, 0x41, 0xE7, 0xDE, + 0x3F, 0x7F, 0x3F, 0x27, 0x28, 0xD3, 0xE3, 0xBC + }; + +/* 32 byte key, 16 bytes of data */ +uint8 key_02[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_02[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + +uint8 ref_02[] = { + 0x10, 0x35, 0xD3, 0xFA, 0xEE, 0xFA, 0xCF, 0x4A, + 0xFE, 0xA5, 0x34, 0x3B, 0xC4, 0xE8, 0x87, 0x6C + }; + +/* 24 byte key, 24 bytes of data */ +uint8 key_03[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + +uint8 input_03[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 ref_03[] = { + 0x2A, 0x82, 0xD7, 0xBB, 0xCF, 0x41, 0xE7, 0xDE, + 0x3F, 0x7F, 0x3F, 0x27, 0x28, 0xD3, 0xE3, 0xBC, + 0xBC, 0xAC, 0x8A, 0x44, 0xFC, 0x5A, 0xFE, 0x8A + }; + +/* 32 byte key, 24 bytes of data */ +uint8 key_04[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_04[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + +uint8 ref_04[] = { + 0x10, 0x35, 0xD3, 0xFA, 0xEE, 0xFA, 0xCF, 0x4A, + 0xFE, 0xA5, 0x34, 0x3B, 0xC4, 0xE8, 0x87, 0x6C, + 0xCC, 0x88, 0x22, 0x77, 0xD7, 0xCB, 0xA2, 0xBA + }; + +/* 32 byte key, 32 bytes of data */ +uint8 key_05[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + +uint8 input_05[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ref_05[] = { + 0x10, 0x35, 0xD3, 0xFA, 0xEE, 0xFA, 0xCF, 0x4A, + 0xFE, 0xA5, 0x34, 0x3B, 0xC4, 0xE8, 0x87, 0x6C, + 0xCC, 0x88, 0x22, 0x77, 0xD7, 0xCB, 0xA2, 0xBA, + 0x6E, 0xF3, 0x2A, 0x82, 0x85, 0xC3, 0xC6, 0x97 + }; + +/* 16 byte key, 32 bytes of data */ +uint8 key_06[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 input_06[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ref_06[] = { + 0xE9, 0x8D, 0x62, 0xCA, 0x03, 0xB7, 0x7F, 0xBB, + 0x8E, 0x42, 0x3D, 0x7D, 0xC2, 0x00, 0xC4, 0xB0, + 0xD3, 0x70, 0x83, 0x5C, 0xF6, 0xB2, 0x44, 0xE9, + 0x87, 0x97, 0xAF, 0xD2, 0xF5, 0x3A, 0xED, 0x0D + }; + +/* RC4 test vectors generated with our tcl rc4 implementation */ +uint8 key_07[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + }; + +uint8 input_07[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +uint8 ref_07[] = { + 0x0f, 0x17, 0xc0, 0x50, 0xbd, 0x01, 0x7f, 0x4a, + 0xce, 0xa1, 0xde, 0xc3, 0x10, 0x2b, 0x16, 0xd1 + }; + +uint8 key_08[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + }; + +uint8 input_08[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + +uint8 ref_08[] = { + 0x0e, 0x15, 0xc3, 0x54, 0xb8, 0x07, 0x78, 0x42, + 0xcf, 0xa3, 0xdd, 0xc7, 0x15, 0x2d, 0x11, 0xd9 + }; + +uint8 key_09[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + }; + +uint8 input_09[] = { + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 + }; + +uint8 ref_09[] = { + 0x1e, 0x05, 0xd3, 0x44, 0xa8, 0x17, 0x68, 0x52, + 0xdf, 0xb3, 0xcd, 0xd7, 0x05, 0x3d, 0x01, 0xc9 + }; + +uint8 key_10[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + }; + +uint8 input_10[] = { + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + +uint8 ref_10[] = { + 0xf1, 0xcb, 0x7a, 0xc8, 0xcb, 0x55, 0x4d, 0x5a, + 0x30, 0x7d, 0x64, 0x5b, 0x66, 0x7f, 0x24, 0xc1 + }; + +uint8 key_11[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d + }; + +uint8 input_11[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +uint8 ref_11[] = { + 0x85, 0x5c, 0xba, 0xe1, 0x78, 0xfa, 0x5c, 0xc2, + 0xf8, 0x81, 0xa2, 0xef, 0xce, 0x49, 0x47, 0xb7 + }; + +uint8 key_12[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d + }; + +uint8 input_12[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + +uint8 ref_12[] = { + 0x84, 0x5e, 0xb9, 0xe5, 0x7d, 0xfc, 0x5b, 0xca, + 0xf9, 0x83, 0xa1, 0xeb, 0xcb, 0x4f, 0x40, 0xbf + }; + +uint8 key_13[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d + }; + +uint8 input_13[] = { + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 + }; + +uint8 ref_13[] = { + 0x94, 0x4e, 0xa9, 0xf5, 0x6d, 0xec, 0x4b, 0xda, + 0xe9, 0x93, 0xb1, 0xfb, 0xdb, 0x5f, 0x50, 0xaf + }; + +uint8 key_14[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d + }; + +uint8 input_14[] = { + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + +uint8 ref_14[] = { + 0x7b, 0x80, 0x00, 0x79, 0x0e, 0xae, 0x6e, 0xd2, + 0x06, 0x5d, 0x18, 0x77, 0xb8, 0x1d, 0x75, 0xa7 + }; + +typedef struct { + int kl; + uint8 *key; + int il; + uint8 *input; + uint8 *ref; +} rc4_vector_t; + +#define RC4_VECTOR_ENTRY(x) \ + { sizeof(key_##x), key_##x, sizeof(input_##x), input_##x, ref_##x } + +rc4_vector_t rc4_vec[] = { + RC4_VECTOR_ENTRY(00), + RC4_VECTOR_ENTRY(01), + RC4_VECTOR_ENTRY(02), + RC4_VECTOR_ENTRY(03), + RC4_VECTOR_ENTRY(04), + RC4_VECTOR_ENTRY(05), + RC4_VECTOR_ENTRY(06), + RC4_VECTOR_ENTRY(07), + RC4_VECTOR_ENTRY(08), + RC4_VECTOR_ENTRY(09), + RC4_VECTOR_ENTRY(10), + RC4_VECTOR_ENTRY(11), + RC4_VECTOR_ENTRY(12), + RC4_VECTOR_ENTRY(13), + RC4_VECTOR_ENTRY(14) + }; diff --git a/release/src-rt/bcmcrypto/rijndael-alg-fst.c b/release/src-rt/bcmcrypto/rijndael-alg-fst.c new file mode 100755 index 0000000000..b0cd850c33 --- /dev/null +++ b/release/src-rt/bcmcrypto/rijndael-alg-fst.c @@ -0,0 +1,1539 @@ +/* + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: rijndael-alg-fst.c,v 1.9 2009-10-28 00:28:59 Exp $ + */ +#include + +/* + * Te0[x] = S [x].[02, 01, 01, 03]; + * Te1[x] = S [x].[03, 02, 01, 01]; + * Te2[x] = S [x].[01, 03, 02, 01]; + * Te3[x] = S [x].[01, 01, 03, 02]; + * Te4[x] = S [x].[01, 01, 01, 01]; + * + * Td0[x] = Si[x].[0e, 09, 0d, 0b]; + * Td1[x] = Si[x].[0b, 0e, 09, 0d]; + * Td2[x] = Si[x].[0d, 0b, 0e, 09]; + * Td3[x] = Si[x].[09, 0d, 0b, 0e]; + * Td4[x] = Si[x].[01, 01, 01, 01]; + */ + +#define Te0 rijndaelTe0 /* Te0[x] can be shared with ccx.c as rijndaelTe0 */ +const uint32 rijndaelTe0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU +}; +static const uint32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U +}; +static const uint32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U +}; +static const uint32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU +}; +static const uint32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U +}; +static const uint32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U +}; +static const uint32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U +}; +static const uint32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U +}; +static const uint32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U +}; +static const uint32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU +}; +static const uint32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000 + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#if defined(_MSC_VER) && !defined(EFI) +#include +#endif + +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) + +#if defined(_MSC_VER) && !defined(EFI) +#define GETU32(p) SWAP(*((uint32 *)(p))) +#define PUTU32(ct, st) { *((uint32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((uint32)(pt)[0] << 24) ^ ((uint32)(pt)[1] << 16) ^ \ + ((uint32)(pt)[2] << 8) ^ ((uint32)(pt)[3])) +#define PUTU32(ct, st) { \ + (ct)[0] = (uint8)((st) >> 24); \ + (ct)[1] = (uint8)((st) >> 16); \ + (ct)[2] = (uint8)((st) >> 8); \ + (ct)[3] = (uint8)(st); } +#endif + +/* + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ + +uint8 _rijndael10 = 10; +uint8 _rijndael8 = 8; +uint8 _rijndael7 = 7; + +int +BCMROMFN(rijndaelKeySetupEnc)(uint32 rk[ /* 4 * (Nr + 1) */], const uint8 cipherKey[], int keyBits) +{ + int i = 0; + uint32 temp; + + rk[0] = GETU32(cipherKey); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == _rijndael10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == _rijndael8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == _rijndael7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/* + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int +BCMROMFN(rijndaelKeySetupDec)(uint32 rk[ /* 4 * (Nr + 1) */ ], const uint8 cipherKey[], int keyBits) +{ + int Nr, i, j; + uint32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i]; rk[i] = rk[j]; rk[j] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0]) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1]) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2]) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3]) & 0xff] & 0xff]; + } + return Nr; +} + +void +BCMROMFN(rijndaelEncrypt)(const uint32 rk[ /* 4 * (Nr + 1) */ ], int Nr, const uint8 pt[16], + uint8 ct[16]) +{ + uint32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct, s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +void +BCMROMFN(rijndaelDecrypt)(const uint32 rk[ /* 4 * (Nr + 1) */], int Nr, const uint8 ct[16], + uint8 pt[16]) +{ + uint32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt, s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); +} + +#ifdef INTERMEDIATE_VALUE_KAT + +void +rijndaelEncryptRound(const uint32 rk[ /* 4 * (Nr + 1) */ ], int Nr, uint8 block[16], int rounds) +{ + int r; + uint32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3) & 0xff] ^ + rk[0]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0) & 0xff] ^ + rk[1]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1) & 0xff] ^ + rk[2]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * apply last round and + * map cipher state to byte array block: + */ + if (rounds == Nr) { + t0 = + (Te4[(s0 >> 24) ] & 0xff000000) ^ + (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s3) & 0xff] & 0x000000ff) ^ + rk[0]; + t1 = + (Te4[(s1 >> 24) ] & 0xff000000) ^ + (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s0) & 0xff] & 0x000000ff) ^ + rk[1]; + t2 = + (Te4[(s2 >> 24) ] & 0xff000000) ^ + (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s1) & 0xff] & 0x000000ff) ^ + rk[2]; + t3 = + (Te4[(s3 >> 24) ] & 0xff000000) ^ + (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s2) & 0xff] & 0x000000ff) ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + PUTU32(block, s0); + PUTU32(block + 4, s1); + PUTU32(block + 8, s2); + PUTU32(block + 12, s3); +} + +void +rijndaelDecryptRound(const uint32 rk[ /* 4 * (Nr + 1) */ ], int Nr, uint8 block[16], int rounds) +{ + int r; + uint32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1) & 0xff] ^ + rk[0]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2) & 0xff] ^ + rk[1]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3) & 0xff] ^ + rk[2]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * complete the last round and + * map cipher state to byte array block: + */ + t0 = + (Td4[(s0 >> 24) ] & 0xff000000) ^ + (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s1) & 0xff] & 0x000000ff); + t1 = + (Td4[(s1 >> 24) ] & 0xff000000) ^ + (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s2) & 0xff] & 0x000000ff); + t2 = + (Td4[(s2 >> 24) ] & 0xff000000) ^ + (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s3) & 0xff] & 0x000000ff); + t3 = + (Td4[(s3 >> 24) ] & 0xff000000) ^ + (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s0) & 0xff] & 0x000000ff); + + if (rounds == Nr) { + t0 ^= rk[0]; + t1 ^= rk[1]; + t2 ^= rk[2]; + t3 ^= rk[3]; + } + + PUTU32(block, t0); + PUTU32(block + 4, t1); + PUTU32(block + 8, t2); + PUTU32(block + 12, t3); +} + +#endif /* INTERMEDIATE_VALUE_KAT */ diff --git a/release/src-rt/bcmcrypto/sha1.c b/release/src-rt/bcmcrypto/sha1.c new file mode 100755 index 0000000000..fa36d3a11f --- /dev/null +++ b/release/src-rt/bcmcrypto/sha1.c @@ -0,0 +1,522 @@ +/* + * Copyright (C) The Internet Society (2001). All Rights Reserved. + * + * This document and translations of it may be copied and furnished to + * others, and derivative works that comment on or otherwise explain it + * or assist in its implementation may be prepared, copied, published + * and distributed, in whole or in part, without restriction of any + * kind, provided that the above copyright notice and this paragraph are + * included on all such copies and derivative works. However, this + * document itself may not be modified in any way, such as by removing + * the copyright notice or references to the Internet Society or other + * Internet organizations, except as needed for the purpose of + * developing Internet standards in which case the procedures for + * copyrights defined in the Internet Standards process must be + * followed, or as required to translate it into languages other than + * English. + * + * The limited permissions granted above are perpetual and will not be + * revoked by the Internet Society or its successors or assigns. + * + * This document and the information contained herein is provided on an + * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: sha1.c,v 1.14 2009-02-26 21:37:35 Exp $ + * + * From rfc3174.txt + */ + +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include + +#ifdef BCMDRIVER +#include +#else +#if defined(__GNUC__) +extern int bcmp(const void *b1, const void *b2, int len); +extern size_t strlen(const char *s); +#else +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#endif /* __GNUC__ */ +#endif /* BCMDRIVER */ + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits, word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +static void SHA1PadMessage(SHA1Context *); +static void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int +BCMROMFN(SHA1Reset)(SHA1Context *context) +{ + if (!context) { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int +BCMROMFN(SHA1Result)(SHA1Context *context, uint8 Message_Digest[SHA1HashSize]) +{ + int i; + + if (!context || !Message_Digest) { + return shaNull; + } + + if (context->Corrupted) { + return context->Corrupted; + } + + if (!context->Computed) { + SHA1PadMessage(context); + for (i = 0; i < 64; ++i) { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + } + + for (i = 0; i < SHA1HashSize; ++i) { + Message_Digest[i] = context->Intermediate_Hash[i >> 2] >> + 8 * (3 - (i & 0x03)); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int +BCMROMFN(SHA1Input)(SHA1Context *context, const uint8 *message_array, unsigned length) +{ + if (!length) { + return shaSuccess; + } + + if (!context || !message_array) { + return shaNull; + } + + if (context->Computed) { + context->Corrupted = shaStateError; + return shaStateError; + } + + if (context->Corrupted) { + return context->Corrupted; + } + while (length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) { + context->Length_High++; + if (context->Length_High == 0) { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +static void +SHA1ProcessMessageBlock(SHA1Context *context) +{ + const uint32 K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32 temp; /* Temporary word value */ + uint32 W[80]; /* Word sequence */ + uint32 A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = context->Message_Block[t * 4] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for (t = 16; t < 80; t++) { + W[t] = SHA1CircularShift(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for (t = 0; t < 20; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + + +/* + * SHA1PadMessage + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +static void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while (context->Message_Block_Index < 64) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } else { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (uint8) (context->Length_High >> 24); + context->Message_Block[57] = (uint8) (context->Length_High >> 16); + context->Message_Block[58] = (uint8) (context->Length_High >> 8); + context->Message_Block[59] = (uint8) (context->Length_High); + context->Message_Block[60] = (uint8) (context->Length_Low >> 24); + context->Message_Block[61] = (uint8) (context->Length_Low >> 16); + context->Message_Block[62] = (uint8) (context->Length_Low >> 8); + context->Message_Block[63] = (uint8) (context->Length_Low); + + SHA1ProcessMessageBlock(context); +} + +#ifdef BCMSHA1_TEST +/* + * sha1test.c + * + * Description: + * This file will exercise the SHA-1 code performing the three + * tests documented in FIPS PUB 180-1 plus one which calls + * SHA1Input with an exact multiple of 512 bits, plus a few + * error test checks. + * + * Portability Issues: + * None. + * + */ + +#include + +/* + * Define patterns for testing + */ +#define TEST1 "abc" +#define TEST2a "abcdbcdecdefdefgefghfghighijhi" +#define TEST2b "jkijkljklmklmnlmnomnopnopq" +#define TEST2 TEST2a TEST2b +#define TEST3 "a" +#define TEST4a "01234567012345670123456701234567" +#define TEST4b "01234567012345670123456701234567" +/* an exact multiple of 512 bits */ +#define TEST4 TEST4a TEST4b +char *testarray[4] = +{ + TEST1, + TEST2, + TEST3, + TEST4 +}; +int repeatcount[4] = { 1, 1, 1000000, 10 }; +uint8 resultarray[4][20] = +{ + {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D}, + {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1}, + {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}, + {0xDE, 0xA3, 0x56, 0xA2, 0xCD, 0xDD, 0x90, 0xC7, 0xA7, 0xEC, + 0xED, 0xC5, 0xEB, 0xB5, 0x63, 0x93, 0x4F, 0x46, 0x04, 0x52} +}; + +int main() +{ + SHA1Context sha; + int i, j, err, fail = 0; + uint8 Message_Digest[20]; + + /* + * Perform SHA-1 tests + */ + for (j = 0; j < 4; ++j) { + printf("\nTest %d: %d, '%s'\n", j + 1, repeatcount[j], testarray[j]); + + err = SHA1Reset(&sha); + if (err) { + fprintf(stderr, "SHA1Reset Error %d.\n", err); + break; /* out of for j loop */ + } + + for (i = 0; i < repeatcount[j]; ++i) { + err = SHA1Input(&sha, + (const unsigned char *) testarray[j], + strlen(testarray[j])); + if (err) { + fprintf(stderr, "SHA1Input Error %d.\n", err); + break; /* out of for i loop */ + } + } + + err = SHA1Result(&sha, Message_Digest); + if (err) { + fprintf(stderr, + "SHA1Result Error %d, could not compute message digest.\n", + err); + } else { + printf("\t"); + for (i = 0; i < 20; ++i) { + printf("%02X ", Message_Digest[i]); + } + printf("\n"); + } + printf("Should match:\n"); + printf("\t"); + for (i = 0; i < 20; ++i) { + printf("%02X ", resultarray[j][i]); + } + printf("\n"); + if (bcmp(Message_Digest, resultarray[j], 20)) fail++; + } + + /* Test some error returns */ + err = SHA1Input(&sha, (const unsigned char *) testarray[1], 1); + printf("\nError %d. Should be %d.\n", err, shaStateError); + if (err != shaStateError) fail++; + + err = SHA1Reset(0); + printf("\nError %d. Should be %d.\n", err, shaNull); + if (err != shaNull) fail++; + + printf("SHA1 test %s\n", fail? "FAILED" : "PASSED"); + return fail; +} +#endif /* BCMSHA1_TEST */ diff --git a/release/src-rt/bcmcrypto/sha256.c b/release/src-rt/bcmcrypto/sha256.c new file mode 100755 index 0000000000..ed6c2e9c91 --- /dev/null +++ b/release/src-rt/bcmcrypto/sha256.c @@ -0,0 +1,445 @@ +/* crypto/sha/sha256.c + * Code copied from openssl distribution and + * Modified just enough so that compiles and runs standalone + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: sha256.c,v 1.2.578.1 2010-05-28 15:25:49 Exp $ + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved + * according to the OpenSSL license [found in ../../LICENSE]. + * ==================================================================== + */ +#ifndef BCMDRIVER +#include +#include +#endif + +#include +#ifdef BCMDRIVER +#include +#else +#include /* for size_t */ +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, size_t len); +extern int bcmp(const void *b1, const void *b2, size_t len); +extern void bzero(void *b, size_t len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif +#endif /* BCMDRIVER */ + +#include + +const char *SHA256_version = "SHA-256"; + +int SHA224_Init(SHA256_CTX *c) + { + c->h[0] = 0xc1059ed8UL; c->h[1] = 0x367cd507UL; + c->h[2] = 0x3070dd17UL; c->h[3] = 0xf70e5939UL; + c->h[4] = 0xffc00b31UL; c->h[5] = 0x68581511UL; + c->h[6] = 0x64f98fa7UL; c->h[7] = 0xbefa4fa4UL; + c->Nl = 0; c->Nh = 0; + c->num = 0; c->md_len = SHA224_DIGEST_LENGTH; + return 1; + } + +int SHA256_Init(SHA256_CTX *c) + { + c->h[0] = 0x6a09e667UL; c->h[1] = 0xbb67ae85UL; + c->h[2] = 0x3c6ef372UL; c->h[3] = 0xa54ff53aUL; + c->h[4] = 0x510e527fUL; c->h[5] = 0x9b05688cUL; + c->h[6] = 0x1f83d9abUL; c->h[7] = 0x5be0cd19UL; + c->Nl = 0; c->Nh = 0; + c->num = 0; c->md_len = SHA256_DIGEST_LENGTH; + return 1; + } + +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md) + { + SHA256_CTX c; + static unsigned char m[SHA224_DIGEST_LENGTH]; + + if (md == NULL) md = m; + SHA224_Init(&c); + SHA256_Update(&c, d, n); + SHA256_Final(md, &c); + return (md); + } + +unsigned char *SHA256(const unsigned char *key, size_t n, unsigned char *md) + { + SHA256_CTX c; + static unsigned char m[SHA256_DIGEST_LENGTH]; + + if (md == NULL) md = m; + SHA256_Init(&c); + SHA256_Update(&c, key, n); + SHA256_Final(md, &c); + return (md); + } + +#ifndef SHA_LONG_LOG2 +#define SHA_LONG_LOG2 2 /* default to 32 bits */ +#endif + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SHA_LONG +#define HASH_LONG_LOG2 SHA_LONG_LOG2 +#define HASH_CTX SHA256_CTX +#define HASH_CBLOCK SHA_CBLOCK +#define HASH_LBLOCK SHA_LBLOCK +/* + * Note that FIPS180-2 discusses "Truncation of the Hash Function Output." + * default: case below covers for it. It's not clear however if it's + * permitted to truncate to amount of bytes not divisible by 4. I bet not, + * but if it is, then default: case shall be extended. For reference. + * Idea behind separate cases for pre-defined lenghts is to let the + * compiler decide if it's appropriate to unroll small loops. + */ +#define HASH_MAKE_STRING(c, s) do { \ + unsigned long ll; \ + unsigned int n; \ + switch ((c)->md_len) \ + { case SHA224_DIGEST_LENGTH: \ + for (n = 0; n < SHA224_DIGEST_LENGTH/4; n++) \ + { ll = (c)->h[n]; HOST_l2c(ll, (s)); } \ + break; \ + case SHA256_DIGEST_LENGTH: \ + for (n = 0; n < SHA256_DIGEST_LENGTH/4; n++) \ + { ll = (c)->h[n]; HOST_l2c(ll, (s)); } \ + break; \ + default: \ + if ((c)->md_len > SHA256_DIGEST_LENGTH) \ + return 0; \ + for (n = 0; n < (c)->md_len/4; n++) \ + { ll = (c)->h[n]; HOST_l2c(ll, (s)); } \ + break; \ + } \ + } while (0) + +#define HASH_UPDATE SHA256_Update +#define HASH_TRANSFORM SHA256_Transform +#define HASH_FINAL SHA256_Final +#define HASH_BLOCK_HOST_ORDER sha256_block_host_order +#define HASH_BLOCK_DATA_ORDER sha256_block_data_order +void sha256_block_host_order(SHA256_CTX *ctx, const void *in, size_t num); +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); + +#include + +#ifdef SHA256_ASM +void sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host); +#else +static const SHA_LONG K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; + +/* + * FIPS specification refers to right rotations, while our ROTATE macro + * is left one. This is why you might notice that rotation coefficients + * differ from those observed in FIPS document by 32-N... + */ +#define Sigma0(x) (ROTATE((x), 30) ^ ROTATE((x), 19) ^ ROTATE((x), 10)) +#define Sigma1(x) (ROTATE((x), 26) ^ ROTATE((x), 21) ^ ROTATE((x), 7)) +#define sigma0(x) (ROTATE((x), 25) ^ ROTATE((x), 14) ^ ((x)>>3)) +#define sigma1(x) (ROTATE((x), 15) ^ ROTATE((x), 13) ^ ((x)>>10)) + +#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#ifdef OPENSSL_SMALL_FOOTPRINT + +static void sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host) + { + unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1, T2; + SHA_LONG X[16]; + int i; + const unsigned char *data = in; + + while (num--) { + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + + if (host) + { + const SHA_LONG *W = (const SHA_LONG *)data; + + for (i = 0; i < 16; i++) + { + T1 = X[i] = W[i]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + T1; + d = c; c = b; b = a; a = T1 + T2; + } + + data += SHA256_CBLOCK; + } + else + { + SHA_LONG l; + + for (i = 0; i < 16; i++) + { + HOST_c2l(data, l); T1 = X[i] = l; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + T1; + d = c; c = b; b = a; a = T1 + T2; + } + } + + for (; i < 64; i++) + { + s0 = X[(i+1)&0x0f]; s0 = sigma0(s0); + s1 = X[(i+14)&0x0f]; s1 = sigma1(s1); + + T1 = X[i&0xf] += s0 + s1 + X[(i+9)&0xf]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + T1; + d = c; c = b; b = a; a = T1 + T2; + } + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; + + } + } + +#else + +#define ROUND_00_15(i, a, b, c, d, e, f, g, h) do { \ + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; \ + h = Sigma0(a) + Maj(a, b, c); \ + d += T1; h += T1; } while (0) + +#define ROUND_16_63(i, a, b, c, d, e, f, g, h, X) do { \ + s0 = X[(i+1)&0x0f]; s0 = sigma0(s0); \ + s1 = X[(i+14)&0x0f]; s1 = sigma1(s1); \ + T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f]; \ + ROUND_00_15(i, a, b, c, d, e, f, g, h); } while (0) + +static void sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host) + { + unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1; + SHA_LONG X[16]; + int i; + const unsigned char *data = in; + + while (num--) { + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + + if (host) + { + const SHA_LONG *W = (const SHA_LONG *)data; + + T1 = X[0] = W[0]; ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = W[1]; ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = W[2]; ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = W[3]; ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = W[4]; ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = W[5]; ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = W[6]; ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = W[7]; ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = W[8]; ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = W[9]; ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = W[10]; ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = W[11]; ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = W[12]; ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = W[13]; ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = W[14]; ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = W[15]; ROUND_00_15(15, b, c, d, e, f, g, h, a); + + data += SHA256_CBLOCK; + } + else + { + SHA_LONG l; + + HOST_c2l(data, l); T1 = X[0] = l; ROUND_00_15(0, a, b, c, d, e, f, g, h); + HOST_c2l(data, l); T1 = X[1] = l; ROUND_00_15(1, h, a, b, c, d, e, f, g); + HOST_c2l(data, l); T1 = X[2] = l; ROUND_00_15(2, g, h, a, b, c, d, e, f); + HOST_c2l(data, l); T1 = X[3] = l; ROUND_00_15(3, f, g, h, a, b, c, d, e); + HOST_c2l(data, l); T1 = X[4] = l; ROUND_00_15(4, e, f, g, h, a, b, c, d); + HOST_c2l(data, l); T1 = X[5] = l; ROUND_00_15(5, d, e, f, g, h, a, b, c); + HOST_c2l(data, l); T1 = X[6] = l; ROUND_00_15(6, c, d, e, f, g, h, a, b); + HOST_c2l(data, l); T1 = X[7] = l; ROUND_00_15(7, b, c, d, e, f, g, h, a); + HOST_c2l(data, l); T1 = X[8] = l; ROUND_00_15(8, a, b, c, d, e, f, g, h); + HOST_c2l(data, l); T1 = X[9] = l; ROUND_00_15(9, h, a, b, c, d, e, f, g); + HOST_c2l(data, l); T1 = X[10] = l; ROUND_00_15(10, g, h, a, b, c, d, e, f); + HOST_c2l(data, l); T1 = X[11] = l; ROUND_00_15(11, f, g, h, a, b, c, d, e); + HOST_c2l(data, l); T1 = X[12] = l; ROUND_00_15(12, e, f, g, h, a, b, c, d); + HOST_c2l(data, l); T1 = X[13] = l; ROUND_00_15(13, d, e, f, g, h, a, b, c); + HOST_c2l(data, l); T1 = X[14] = l; ROUND_00_15(14, c, d, e, f, g, h, a, b); + HOST_c2l(data, l); T1 = X[15] = l; ROUND_00_15(15, b, c, d, e, f, g, h, a); + } + + for (i = 16; i < 64; i += 8) + { + ROUND_16_63(i+0, a, b, c, d, e, f, g, h, X); + ROUND_16_63(i+1, h, a, b, c, d, e, f, g, X); + ROUND_16_63(i+2, g, h, a, b, c, d, e, f, X); + ROUND_16_63(i+3, f, g, h, a, b, c, d, e, X); + ROUND_16_63(i+4, e, f, g, h, a, b, c, d, X); + ROUND_16_63(i+5, d, e, f, g, h, a, b, c, X); + ROUND_16_63(i+6, c, d, e, f, g, h, a, b, X); + ROUND_16_63(i+7, b, c, d, e, f, g, h, a, X); + } + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; + + } + } + +#endif /* OPENSSL_SMALL_FOOTPRINT */ +#endif /* SHA256_ASM */ + +/* + * Idea is to trade couple of cycles for some space. On IA-32 we save + * about 4K in "big footprint" case. In "small footprint" case any gain + * is appreciated:-) + */ +void HASH_BLOCK_HOST_ORDER(SHA256_CTX *ctx, const void *in, size_t num) +{ sha256_block(ctx, in, num, 1); } + +void HASH_BLOCK_DATA_ORDER(SHA256_CTX *ctx, const void *in, size_t num) +{ sha256_block(ctx, in, num, 0); } + + +#ifdef BCMSHA256_TEST +/* + * sha1test.c + * + * Description: + * This file will exercise the SHA-256 code performing the three + * tests documented in FIPS PUB 180-2 plus one which calls + * SHA1Input with an exact multiple of 512 bits, plus a few + * error test checks. + * + * Portability Issues: + * None. + * + */ + +#include + +/* + * Define patterns for testing + */ +#define TEST1 "abc" +#define TEST2a "abcdbcdecdefdefgefghfghighijhi" +#define TEST2b "jkijkljklmklmnlmnomnopnopq" +#define TEST2 TEST2a TEST2b +#define TEST3 "a" + +char *testarray[3] = +{ + TEST1, + TEST2, + TEST3 +}; + + +int repeatcount[3] = { 1, 1, 1000000}; +unsigned char resultarray[3][32] = +{ + {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, + + {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, + + {0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, + 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, + 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, + 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0} +}; + +int main() +{ + SHA256_CTX sha; + int i, j, err, fail = 0; + unsigned char Message_Digest[32]; + + /* + * Perform SHA-1 tests + */ + for (j = 0; j < 3; ++j) { + printf("\nTest %d: %d, '%s'\n", j + 1, repeatcount[j], testarray[j]); + + err = SHA256_Init(&sha); + + for (i = 0; i < repeatcount[j]; ++i) { + err = SHA256_Update(&sha, + (const unsigned char *) testarray[j], + strlen(testarray[j])); + } + + err = SHA256_Final(Message_Digest, &sha); + printf("\t"); + for (i = 0; i < 32; ++i) { + printf("%02X ", Message_Digest[i]); + } + printf("\n"); + printf("Should match:\n"); + printf("\t"); + for (i = 0; i < 32; ++i) { + printf("%02X ", resultarray[j][i]); + } + printf("\n"); + if (bcmp(Message_Digest, resultarray[j], 32)) fail++; + } +#ifdef EXTRA_SHA256_TEST + /* Test some error returns */ + err = SHA1Input(&sha, (const unsigned char *) testarray[1], 1); + printf("\nError %d. Should be %d.\n", err, shaStateError); + if (err != shaStateError) fail++; + + err = SHA1Reset(0); + printf("\nError %d. Should be %d.\n", err, shaNull); + if (err != shaNull) fail++; +#endif + printf("SHA1 test %s\n", fail? "FAILED" : "PASSED"); + return fail; +} +#endif /* BCMSHA1_TEST */ diff --git a/release/src-rt/bcmcrypto/sms4.c b/release/src-rt/bcmcrypto/sms4.c new file mode 100755 index 0000000000..8a05986517 --- /dev/null +++ b/release/src-rt/bcmcrypto/sms4.c @@ -0,0 +1,1375 @@ +#ifdef BCMWAPI_WPI +/* + * sms4.c + * SMS-4 block cipher + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: sms4.c,v 1.23 2009-10-22 00:10:59 Exp $ + */ + +#include +#include +#include +#include + +#include + +#ifdef BCMDRIVER +#include +#else +#include /* for size_t */ +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, size_t len); +extern int bcmp(const void *b1, const void *b2, size_t len); +extern void bzero(void *b, size_t len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif /* __GNUC__ */ +#endif /* BCMDRIVER */ + +#define ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +static void +sms4_print_bytes(char *name, const uchar *data, int len) +{ +} + +#if !defined(__i386__) +static const uint8 S_box[] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 +}; +#else /* __i386__ */ +/* slightly better performance on Pentium, worse performance on ARM CM3 */ +static const uint32 S_box0[] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 +}; + +static const uint32 S_box1[] = { + 0xd600, 0x9000, 0xe900, 0xfe00, 0xcc00, 0xe100, 0x3d00, 0xb700, + 0x1600, 0xb600, 0x1400, 0xc200, 0x2800, 0xfb00, 0x2c00, 0x0500, + 0x2b00, 0x6700, 0x9a00, 0x7600, 0x2a00, 0xbe00, 0x0400, 0xc300, + 0xaa00, 0x4400, 0x1300, 0x2600, 0x4900, 0x8600, 0x0600, 0x9900, + 0x9c00, 0x4200, 0x5000, 0xf400, 0x9100, 0xef00, 0x9800, 0x7a00, + 0x3300, 0x5400, 0x0b00, 0x4300, 0xed00, 0xcf00, 0xac00, 0x6200, + 0xe400, 0xb300, 0x1c00, 0xa900, 0xc900, 0x0800, 0xe800, 0x9500, + 0x8000, 0xdf00, 0x9400, 0xfa00, 0x7500, 0x8f00, 0x3f00, 0xa600, + 0x4700, 0x0700, 0xa700, 0xfc00, 0xf300, 0x7300, 0x1700, 0xba00, + 0x8300, 0x5900, 0x3c00, 0x1900, 0xe600, 0x8500, 0x4f00, 0xa800, + 0x6800, 0x6b00, 0x8100, 0xb200, 0x7100, 0x6400, 0xda00, 0x8b00, + 0xf800, 0xeb00, 0x0f00, 0x4b00, 0x7000, 0x5600, 0x9d00, 0x3500, + 0x1e00, 0x2400, 0x0e00, 0x5e00, 0x6300, 0x5800, 0xd100, 0xa200, + 0x2500, 0x2200, 0x7c00, 0x3b00, 0x0100, 0x2100, 0x7800, 0x8700, + 0xd400, 0x0000, 0x4600, 0x5700, 0x9f00, 0xd300, 0x2700, 0x5200, + 0x4c00, 0x3600, 0x0200, 0xe700, 0xa000, 0xc400, 0xc800, 0x9e00, + 0xea00, 0xbf00, 0x8a00, 0xd200, 0x4000, 0xc700, 0x3800, 0xb500, + 0xa300, 0xf700, 0xf200, 0xce00, 0xf900, 0x6100, 0x1500, 0xa100, + 0xe000, 0xae00, 0x5d00, 0xa400, 0x9b00, 0x3400, 0x1a00, 0x5500, + 0xad00, 0x9300, 0x3200, 0x3000, 0xf500, 0x8c00, 0xb100, 0xe300, + 0x1d00, 0xf600, 0xe200, 0x2e00, 0x8200, 0x6600, 0xca00, 0x6000, + 0xc000, 0x2900, 0x2300, 0xab00, 0x0d00, 0x5300, 0x4e00, 0x6f00, + 0xd500, 0xdb00, 0x3700, 0x4500, 0xde00, 0xfd00, 0x8e00, 0x2f00, + 0x0300, 0xff00, 0x6a00, 0x7200, 0x6d00, 0x6c00, 0x5b00, 0x5100, + 0x8d00, 0x1b00, 0xaf00, 0x9200, 0xbb00, 0xdd00, 0xbc00, 0x7f00, + 0x1100, 0xd900, 0x5c00, 0x4100, 0x1f00, 0x1000, 0x5a00, 0xd800, + 0x0a00, 0xc100, 0x3100, 0x8800, 0xa500, 0xcd00, 0x7b00, 0xbd00, + 0x2d00, 0x7400, 0xd000, 0x1200, 0xb800, 0xe500, 0xb400, 0xb000, + 0x8900, 0x6900, 0x9700, 0x4a00, 0x0c00, 0x9600, 0x7700, 0x7e00, + 0x6500, 0xb900, 0xf100, 0x0900, 0xc500, 0x6e00, 0xc600, 0x8400, + 0x1800, 0xf000, 0x7d00, 0xec00, 0x3a00, 0xdc00, 0x4d00, 0x2000, + 0x7900, 0xee00, 0x5f00, 0x3e00, 0xd700, 0xcb00, 0x3900, 0x4800 +}; + +static const uint32 S_box2[] = { + 0xd60000, 0x900000, 0xe90000, 0xfe0000, + 0xcc0000, 0xe10000, 0x3d0000, 0xb70000, + 0x160000, 0xb60000, 0x140000, 0xc20000, + 0x280000, 0xfb0000, 0x2c0000, 0x050000, + 0x2b0000, 0x670000, 0x9a0000, 0x760000, + 0x2a0000, 0xbe0000, 0x040000, 0xc30000, + 0xaa0000, 0x440000, 0x130000, 0x260000, + 0x490000, 0x860000, 0x060000, 0x990000, + 0x9c0000, 0x420000, 0x500000, 0xf40000, + 0x910000, 0xef0000, 0x980000, 0x7a0000, + 0x330000, 0x540000, 0x0b0000, 0x430000, + 0xed0000, 0xcf0000, 0xac0000, 0x620000, + 0xe40000, 0xb30000, 0x1c0000, 0xa90000, + 0xc90000, 0x080000, 0xe80000, 0x950000, + 0x800000, 0xdf0000, 0x940000, 0xfa0000, + 0x750000, 0x8f0000, 0x3f0000, 0xa60000, + 0x470000, 0x070000, 0xa70000, 0xfc0000, + 0xf30000, 0x730000, 0x170000, 0xba0000, + 0x830000, 0x590000, 0x3c0000, 0x190000, + 0xe60000, 0x850000, 0x4f0000, 0xa80000, + 0x680000, 0x6b0000, 0x810000, 0xb20000, + 0x710000, 0x640000, 0xda0000, 0x8b0000, + 0xf80000, 0xeb0000, 0x0f0000, 0x4b0000, + 0x700000, 0x560000, 0x9d0000, 0x350000, + 0x1e0000, 0x240000, 0x0e0000, 0x5e0000, + 0x630000, 0x580000, 0xd10000, 0xa20000, + 0x250000, 0x220000, 0x7c0000, 0x3b0000, + 0x010000, 0x210000, 0x780000, 0x870000, + 0xd40000, 0x000000, 0x460000, 0x570000, + 0x9f0000, 0xd30000, 0x270000, 0x520000, + 0x4c0000, 0x360000, 0x020000, 0xe70000, + 0xa00000, 0xc40000, 0xc80000, 0x9e0000, + 0xea0000, 0xbf0000, 0x8a0000, 0xd20000, + 0x400000, 0xc70000, 0x380000, 0xb50000, + 0xa30000, 0xf70000, 0xf20000, 0xce0000, + 0xf90000, 0x610000, 0x150000, 0xa10000, + 0xe00000, 0xae0000, 0x5d0000, 0xa40000, + 0x9b0000, 0x340000, 0x1a0000, 0x550000, + 0xad0000, 0x930000, 0x320000, 0x300000, + 0xf50000, 0x8c0000, 0xb10000, 0xe30000, + 0x1d0000, 0xf60000, 0xe20000, 0x2e0000, + 0x820000, 0x660000, 0xca0000, 0x600000, + 0xc00000, 0x290000, 0x230000, 0xab0000, + 0x0d0000, 0x530000, 0x4e0000, 0x6f0000, + 0xd50000, 0xdb0000, 0x370000, 0x450000, + 0xde0000, 0xfd0000, 0x8e0000, 0x2f0000, + 0x030000, 0xff0000, 0x6a0000, 0x720000, + 0x6d0000, 0x6c0000, 0x5b0000, 0x510000, + 0x8d0000, 0x1b0000, 0xaf0000, 0x920000, + 0xbb0000, 0xdd0000, 0xbc0000, 0x7f0000, + 0x110000, 0xd90000, 0x5c0000, 0x410000, + 0x1f0000, 0x100000, 0x5a0000, 0xd80000, + 0x0a0000, 0xc10000, 0x310000, 0x880000, + 0xa50000, 0xcd0000, 0x7b0000, 0xbd0000, + 0x2d0000, 0x740000, 0xd00000, 0x120000, + 0xb80000, 0xe50000, 0xb40000, 0xb00000, + 0x890000, 0x690000, 0x970000, 0x4a0000, + 0x0c0000, 0x960000, 0x770000, 0x7e0000, + 0x650000, 0xb90000, 0xf10000, 0x090000, + 0xc50000, 0x6e0000, 0xc60000, 0x840000, + 0x180000, 0xf00000, 0x7d0000, 0xec0000, + 0x3a0000, 0xdc0000, 0x4d0000, 0x200000, + 0x790000, 0xee0000, 0x5f0000, 0x3e0000, + 0xd70000, 0xcb0000, 0x390000, 0x480000 +}; + +static const uint32 S_box3[] = { + 0xd6000000, 0x90000000, 0xe9000000, 0xfe000000, + 0xcc000000, 0xe1000000, 0x3d000000, 0xb7000000, + 0x16000000, 0xb6000000, 0x14000000, 0xc2000000, + 0x28000000, 0xfb000000, 0x2c000000, 0x05000000, + 0x2b000000, 0x67000000, 0x9a000000, 0x76000000, + 0x2a000000, 0xbe000000, 0x04000000, 0xc3000000, + 0xaa000000, 0x44000000, 0x13000000, 0x26000000, + 0x49000000, 0x86000000, 0x06000000, 0x99000000, + 0x9c000000, 0x42000000, 0x50000000, 0xf4000000, + 0x91000000, 0xef000000, 0x98000000, 0x7a000000, + 0x33000000, 0x54000000, 0x0b000000, 0x43000000, + 0xed000000, 0xcf000000, 0xac000000, 0x62000000, + 0xe4000000, 0xb3000000, 0x1c000000, 0xa9000000, + 0xc9000000, 0x08000000, 0xe8000000, 0x95000000, + 0x80000000, 0xdf000000, 0x94000000, 0xfa000000, + 0x75000000, 0x8f000000, 0x3f000000, 0xa6000000, + 0x47000000, 0x07000000, 0xa7000000, 0xfc000000, + 0xf3000000, 0x73000000, 0x17000000, 0xba000000, + 0x83000000, 0x59000000, 0x3c000000, 0x19000000, + 0xe6000000, 0x85000000, 0x4f000000, 0xa8000000, + 0x68000000, 0x6b000000, 0x81000000, 0xb2000000, + 0x71000000, 0x64000000, 0xda000000, 0x8b000000, + 0xf8000000, 0xeb000000, 0x0f000000, 0x4b000000, + 0x70000000, 0x56000000, 0x9d000000, 0x35000000, + 0x1e000000, 0x24000000, 0x0e000000, 0x5e000000, + 0x63000000, 0x58000000, 0xd1000000, 0xa2000000, + 0x25000000, 0x22000000, 0x7c000000, 0x3b000000, + 0x01000000, 0x21000000, 0x78000000, 0x87000000, + 0xd4000000, 0x00000000, 0x46000000, 0x57000000, + 0x9f000000, 0xd3000000, 0x27000000, 0x52000000, + 0x4c000000, 0x36000000, 0x02000000, 0xe7000000, + 0xa0000000, 0xc4000000, 0xc8000000, 0x9e000000, + 0xea000000, 0xbf000000, 0x8a000000, 0xd2000000, + 0x40000000, 0xc7000000, 0x38000000, 0xb5000000, + 0xa3000000, 0xf7000000, 0xf2000000, 0xce000000, + 0xf9000000, 0x61000000, 0x15000000, 0xa1000000, + 0xe0000000, 0xae000000, 0x5d000000, 0xa4000000, + 0x9b000000, 0x34000000, 0x1a000000, 0x55000000, + 0xad000000, 0x93000000, 0x32000000, 0x30000000, + 0xf5000000, 0x8c000000, 0xb1000000, 0xe3000000, + 0x1d000000, 0xf6000000, 0xe2000000, 0x2e000000, + 0x82000000, 0x66000000, 0xca000000, 0x60000000, + 0xc0000000, 0x29000000, 0x23000000, 0xab000000, + 0x0d000000, 0x53000000, 0x4e000000, 0x6f000000, + 0xd5000000, 0xdb000000, 0x37000000, 0x45000000, + 0xde000000, 0xfd000000, 0x8e000000, 0x2f000000, + 0x03000000, 0xff000000, 0x6a000000, 0x72000000, + 0x6d000000, 0x6c000000, 0x5b000000, 0x51000000, + 0x8d000000, 0x1b000000, 0xaf000000, 0x92000000, + 0xbb000000, 0xdd000000, 0xbc000000, 0x7f000000, + 0x11000000, 0xd9000000, 0x5c000000, 0x41000000, + 0x1f000000, 0x10000000, 0x5a000000, 0xd8000000, + 0x0a000000, 0xc1000000, 0x31000000, 0x88000000, + 0xa5000000, 0xcd000000, 0x7b000000, 0xbd000000, + 0x2d000000, 0x74000000, 0xd0000000, 0x12000000, + 0xb8000000, 0xe5000000, 0xb4000000, 0xb0000000, + 0x89000000, 0x69000000, 0x97000000, 0x4a000000, + 0x0c000000, 0x96000000, 0x77000000, 0x7e000000, + 0x65000000, 0xb9000000, 0xf1000000, 0x09000000, + 0xc5000000, 0x6e000000, 0xc6000000, 0x84000000, + 0x18000000, 0xf0000000, 0x7d000000, 0xec000000, + 0x3a000000, 0xdc000000, 0x4d000000, 0x20000000, + 0x79000000, 0xee000000, 0x5f000000, 0x3e000000, + 0xd7000000, 0xcb000000, 0x39000000, 0x48000000 +}; +#endif /* __i386__ */ + +/* Non-linear transform + * A = (a0, a1, a2, a3) + * B = (b0, b1, b2, b3) + * (b0, b1, b2, b3) = tau(A) = (Sbox(a0), Sbox(a1), Sbox(a2), Sbox(a3)) + */ +static INLINE uint32 +tau(uint32 A) +{ + uint32 B; + +#if !defined(__i386__) + B = (S_box[A & 0xff] | + (S_box[(A & 0xff00) >> 8] << 8) | + (S_box[(A & 0xff0000) >> 16] << 16) | + (S_box[(A & 0xff000000) >> 24] << 24)); +#else /* __i386__ */ +/* slightly better performance on Pentium, worse performance on ARM CM3 */ + B = (S_box0[A & 0xff] | + S_box1[(A & 0xff00) >> 8] | + S_box2[(A & 0xff0000) >> 16] | + S_box3[(A & 0xff000000) >> 24]); +#endif /* __i386__ */ + + return (B); +} + +/* Linear transform + * C = L(B) = B ^ (B<<<2) ^ (B<<<10) ^ (B<<<18) ^ (B<<<24) + * where "<<<" is a circular left shift + */ +static INLINE uint32 +L(uint32 B) +{ + uint32 Ba = B ^ ROTATE(B, 24); + return (Ba ^ ROTATE((ROTATE(Ba, 16) ^ B), 2)); +} + +/* Compound Transform + * T(.) = L(tau(.)) + */ +static INLINE uint32 +T(uint32 X) +{ + return (L(tau(X))); +} + +/* Round Function + * F(X0,X1,X2,X3,RK) = X0 ^ T(X1^X2^X3^RK) + * static INLINE uint32 + * F(uint32 *X, uint32 RK) + * { + * return (X[0] ^ T(X[1] ^ X[2] ^ X[3] ^ RK)); + * } + */ + +/* Encryption/decryption algorithm + * Xi+4 = F(Xi, Xi+1, Xi+2, Xi+3, RKj) = Xi ^ T(Xi+1 ^ Xi+2 ^ Xi+3 ^ RKj) + * i=0,1,...31, j=i(enc) or j=31-i(dec) + * (Y0, Y1, Y2, Y3) = (X35, X34, X33, X32) + */ + +/* define SMS4_FULL_UNROLL to completely unroll F() - results in slightly faster but bigger code */ +#define SMS4_FULL_UNROLL + +void +sms4_enc(uint32 *Y, uint32 *X, const uint32 *RK) +{ + uint32 z0 = X[0], z1 = X[1], z2 = X[2], z3 = X[3]; +#ifndef SMS4_FULL_UNROLL + int i; + + for (i = 0; i < SMS4_RK_WORDS; i += 4) { + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + } +#else /* SMS4_FULL_UNROLL */ + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); + z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++); + z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++); + z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++); + z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++); +#endif /* SMS4_FULL_UNROLL */ + + Y[0] = z3; + Y[1] = z2; + Y[2] = z1; + Y[3] = z0; +} + +void +sms4_dec(uint32 *Y, uint32 *X, uint32 *RK) +{ + uint32 z0 = X[0], z1 = X[1], z2 = X[2], z3 = X[3]; + int i; + + RK += 32; + + for (i = 0; i < SMS4_RK_WORDS; i += 4) { + z0 ^= T(z1 ^ z2 ^ z3 ^ *--RK); + z1 ^= T(z2 ^ z3 ^ z0 ^ *--RK); + z2 ^= T(z3 ^ z0 ^ z1 ^ *--RK); + z3 ^= T(z0 ^ z1 ^ z2 ^ *--RK); + } + + Y[0] = z3; + Y[1] = z2; + Y[2] = z1; + Y[3] = z0; +} + +static const uint32 CK[] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 +}; + +static const uint32 FK[] = { + 0xA3B1BAC6, + 0x56AA3350, + 0x677D9197, + 0xB27022DC +}; + +/* Key Expansion Linear transform + * Lprime(B) = B ^ (B<<<13) ^ (B<<<23) + * where "<<<" is a circular left shift + */ +static INLINE uint32 +Lprime(uint32 B) +{ + return (B ^ ROTATE(B, 13) ^ ROTATE(B, 23)); +} + +/* Key Expansion Compound Transform + * Tprime(.) = Lprime(tau(.)) + */ +static INLINE uint32 +Tprime(uint32 X) +{ + return (Lprime(tau(X))); +} + +/* Key Expansion + * Encryption key MK = (MK0, MK1, MK2, MK3) + * (K0, K1, K2, K3) = (MK0 ^ FK0, MK1 ^ FK1, MK2 ^ FK2, MK3 ^ FK3) + * RKi = Ki+4 = Ki ^ Tprime(Ki+1 ^ Ki+2 ^ Ki+3 ^ CKi+4) + */ +void +sms4_key_exp(uint32 *MK, uint32 *RK) +{ + int i; + uint32 K[36]; + + for (i = 0; i < 4; i++) + K[i] = MK[i] ^ FK[i]; + + for (i = 0; i < SMS4_RK_WORDS; i++) { + K[i+4] = K[i] ^ Tprime(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]); + RK[i] = K[i+4]; + } + + return; +} + +/* SMS4-CBC-MAC mode for WPI + * - computes SMS4_WPI_CBC_MAC_LEN MAC + * - Integrity Check Key must be SMS4_KEY_LEN bytes + * - PN must be SMS4_WPI_PN_LEN bytes + * - AAD inludes Key Index, Reserved, and L (data len) fields + * - For MAC calculation purposes, the aad and data are each padded with + * NULLs to a multiple of the block size + * - ptxt must have sufficient tailroom for storing the MAC + * - returns -1 on error + * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_CBC_MAC_ERROR on error + */ +int +sms4_wpi_cbc_mac(const uint8 *ick, + const uint8 *pn, + const size_t aad_len, + const uint8 *aad, + uint8 *ptxt) +{ + int k, j, rem_len; + uint32 RK[SMS4_RK_WORDS]; + uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS]; + uint8 tmp[SMS4_BLOCK_SZ]; + uint16 data_len = (aad[aad_len-2] << 8) | (aad[aad_len-1]); + + if (data_len > SMS4_WPI_MAX_MPDU_LEN) + return (SMS4_WPI_CBC_MAC_ERROR); + + sms4_print_bytes("MIC Key", (uchar *)ick, SMS4_WPI_CBC_MAC_LEN); + sms4_print_bytes("PN ", (uchar *)pn, SMS4_WPI_PN_LEN); + sms4_print_bytes("MIC data: PART1", (uchar *)aad, aad_len); + sms4_print_bytes("MIC data: PART 2", (uchar *)ptxt, data_len); + + /* Prepare the round key */ + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)ick & 3) + X[k] = ntoh32_ua(ick + (SMS4_WORD_SZ * k)); + else + X[k] = ntoh32(*(uint32 *)(ick + (SMS4_WORD_SZ * k))); + sms4_key_exp(X, RK); + + /* First block: PN */ + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)pn & 3) + X[k] = ntoh32_ua(pn + (SMS4_WORD_SZ * k)); + else + X[k] = ntoh32(*(uint32 *)(pn + (SMS4_WORD_SZ * k))); + sms4_enc(Y, X, RK); + + /* Next blocks: AAD */ + for (j = 0; j < aad_len/SMS4_BLOCK_SZ; j++) { + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)aad & 3) + X[k] = Y[k] ^ ntoh32_ua(aad + (SMS4_WORD_SZ * k)); + else + X[k] = Y[k] ^ ntoh32(*(uint32 *)(aad + (SMS4_WORD_SZ * k))); + aad += SMS4_BLOCK_SZ; + sms4_enc(Y, X, RK); + } + /* If the last block is partial, pad with NULLs */ + rem_len = aad_len % SMS4_BLOCK_SZ; + if (rem_len) { + bcopy(aad, tmp, rem_len); + bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len); + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)tmp & 3) + X[k] = Y[k] ^ ntoh32_ua(tmp + (SMS4_WORD_SZ * k)); + else + X[k] = Y[k] ^ ntoh32(*(uint32 *)(tmp + (SMS4_WORD_SZ * k))); + sms4_enc(Y, X, RK); + } + + /* Then the message data */ + for (j = 0; j < (data_len / SMS4_BLOCK_SZ); j++) { + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)ptxt & 3) + X[k] = Y[k] ^ ntoh32_ua(ptxt + (SMS4_WORD_SZ * k)); + else + X[k] = Y[k] ^ ntoh32(*(uint32 *)(ptxt + (SMS4_WORD_SZ * k))); + ptxt += SMS4_BLOCK_SZ; + sms4_enc(Y, X, RK); + } + /* If the last block is partial, pad with NULLs */ + rem_len = data_len % SMS4_BLOCK_SZ; + if (rem_len) { + bcopy(ptxt, tmp, rem_len); + bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len); + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)tmp & 3) + X[k] = Y[k] ^ ntoh32_ua(tmp + (SMS4_WORD_SZ * k)); + else + X[k] = Y[k] ^ ntoh32(*(uint32 *)(tmp + (SMS4_WORD_SZ * k))); + ptxt += data_len % SMS4_BLOCK_SZ; + sms4_enc(Y, X, RK); + } + + for (k = 0; k < SMS4_BLOCK_WORDS; k++) { + hton32_ua_store(Y[k], ptxt); + ptxt += SMS4_WORD_SZ; + } + + return (SMS4_WPI_SUCCESS); +} + +/* + * ick pn ptxt result + * ltoh ltoh ltoh fail + * ntoh ltoh ltoh fail + * ltoh ntoh ltoh fail + * ntoh ntoh ltoh fail + * + * ltoh ltoh ntoh fail + * ntoh ltoh ntoh fail + * ltoh ntoh ntoh fail + * ntoh ntoh ntoh fail + */ + +#define s_ick(a) ntoh32_ua(a) +#define s_pn(a) ntoh32_ua(a) +#define s_ptxt(a) ntoh32_ua(a) + +#ifdef BCMSMS4_TEST +static int sms4_cbc_mac(const uint8 *ick, const uint8 *pn, const size_t data_len, + uint8 *ptxt, uint8 *mac); +static int +sms4_cbc_mac(const uint8 *ick, + const uint8 *pn, + const size_t data_len, + uint8 *ptxt, + uint8 *mac) +{ + int k, j, rem_len; + uint32 RK[SMS4_RK_WORDS]; + uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS]; + uint8 tmp[SMS4_BLOCK_SZ]; + + if (data_len > SMS4_WPI_MAX_MPDU_LEN) + return (SMS4_WPI_CBC_MAC_ERROR); + + /* Prepare the round key */ + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + X[k] = s_ick(ick + (SMS4_WORD_SZ * k)); + sms4_key_exp(X, RK); + + /* First block: PN */ + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + X[k] = s_pn(pn + (SMS4_WORD_SZ * k)); + sms4_enc(Y, X, RK); + + /* Then the message data */ + for (j = 0; j < (data_len / SMS4_BLOCK_SZ); j++) { + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + X[k] = Y[k] ^ s_ptxt(ptxt + (SMS4_WORD_SZ * k)); + ptxt += SMS4_BLOCK_SZ; + sms4_enc(Y, X, RK); + } + /* If the last block is partial, pad with NULLs */ + rem_len = data_len % SMS4_BLOCK_SZ; + if (rem_len) { + bcopy(ptxt, tmp, rem_len); + bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len); + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + X[k] = Y[k] ^ s_ptxt(tmp + (SMS4_WORD_SZ * k)); + ptxt += data_len % SMS4_BLOCK_SZ; + sms4_enc(Y, X, RK); + } + + for (k = 0; k < SMS4_BLOCK_WORDS; k++) { + hton32_ua_store(Y[k], mac); + mac += SMS4_WORD_SZ; + } + + return (SMS4_WPI_SUCCESS); +} +#endif /* BCMSMS4_TEST */ + +/* SMS4-OFB mode encryption/decryption algorithm + * - PN must be SMS4_WPI_PN_LEN bytes + * - assumes PN is ready to use as-is (i.e. any + * randomization of PN is handled by the caller) + * - encrypts data in place + * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_OFB_ERROR on error + */ +int +sms4_ofb_crypt(const uint8 *ek, + const uint8 *pn, + const size_t data_len, + uint8 *ptxt) +{ + size_t j, k; + uint8 tmp[SMS4_BLOCK_SZ]; + uint32 RK[SMS4_RK_WORDS]; + uint32 X[SMS4_BLOCK_WORDS]; + + if (data_len > SMS4_WPI_MAX_MPDU_LEN) return (SMS4_WPI_OFB_ERROR); + + sms4_print_bytes("ENC Key", (uchar *)ek, SMS4_WPI_CBC_MAC_LEN); + sms4_print_bytes("PN ", (uint8 *)pn, SMS4_WPI_PN_LEN); + sms4_print_bytes("data", (uchar *)ptxt, data_len); + + /* Prepare the round key */ + for (k = 0; k < SMS4_BLOCK_WORDS; k++) + if ((uintptr)ek & 3) + X[k] = ntoh32_ua(ek + (SMS4_WORD_SZ * k)); + else + X[k] = ntoh32(*(uint32 *)(ek + (SMS4_WORD_SZ * k))); + sms4_key_exp(X, RK); + + for (k = 0; k < SMS4_BLOCK_WORDS; k++) { + if ((uintptr)pn & 3) + X[k] = ntoh32_ua(pn + (SMS4_WORD_SZ * k)); + else + X[k] = ntoh32(*(uint32 *)(pn + (SMS4_WORD_SZ * k))); + } + + for (k = 0; k < (data_len / SMS4_BLOCK_SZ); k++) { + sms4_enc(X, X, RK); + for (j = 0; j < SMS4_BLOCK_WORDS; j++) { + hton32_ua_store(X[j], &tmp[j * SMS4_WORD_SZ]); + } + xor_128bit_block(ptxt, tmp, ptxt); + ptxt += SMS4_BLOCK_SZ; + } + + /* handle partial block */ + if (data_len % SMS4_BLOCK_SZ) { + sms4_enc(X, X, RK); + for (j = 0; j < SMS4_BLOCK_WORDS; j++) { + hton32_ua_store(X[j], &tmp[j * SMS4_WORD_SZ]); + } + for (k = 0; k < (data_len % SMS4_BLOCK_SZ); k++) + ptxt[k] ^= tmp[k]; + } + + return (SMS4_WPI_SUCCESS); +} + +/* SMS4-WPI mode encryption of 802.11 packet + * - constructs aad and pn from provided frame + * - calls sms4_wpi_cbc_mac() to compute MAC + * - calls sms4_ofb_crypt() to encrypt frame + * - encrypts data in place + * - supplied packet must have sufficient tailroom for CBC-MAC MAC + * - data_len includes 802.11 header and CBC-MAC MAC + * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_ENCRYPT_ERROR on error + */ +int +sms4_wpi_pkt_encrypt(const uint8 *ek, + const uint8 *ick, + const size_t data_len, + uint8 *p) +{ + uint8 aad[SMS4_WPI_MAX_AAD_LEN]; + uint8 *paad = aad; + struct dot11_header *h = (struct dot11_header *)p; + struct wpi_iv *iv_data; + uint16 fc, seq; + uint header_len, aad_len, qos_len = 0, hdr_add_len = 0; + bool wds = FALSE; + uint8 tmp[SMS4_BLOCK_SZ]; + int k; + + bzero(aad, SMS4_WPI_MAX_AAD_LEN); + + fc = ltoh16_ua(&(h->fc)); + + /* WPI only supports protection of DATA frames */ + if (FC_TYPE(fc) != FC_TYPE_DATA) + return (SMS4_WPI_ENCRYPT_ERROR); + + /* frame must have Protected flag set */ + if (!(fc & FC_WEP)) + return (SMS4_WPI_ENCRYPT_ERROR); + + /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */ + if (FC_SUBTYPE(fc) & FC_SUBTYPE_QOS_DATA) + qos_len += 2; + + /* length of A4, if using wds frames */ + wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS)); + if (wds) + hdr_add_len += ETHER_ADDR_LEN; + + /* length of MPDU header, including PN */ + header_len = DOT11_A3_HDR_LEN + SMS4_WPI_IV_LEN + hdr_add_len + qos_len; + + /* pointer to IV */ + iv_data = (struct wpi_iv *)(p + DOT11_A3_HDR_LEN + qos_len + hdr_add_len); + + /* Payload must be > 0 bytes */ + if (data_len <= (header_len + SMS4_WPI_CBC_MAC_LEN)) + return (SMS4_WPI_ENCRYPT_ERROR); + + /* aad: maskedFC || A1 || A2 || maskedSC || A3 || A4 || KeyIdx || Reserved || L */ + + fc &= SMS4_WPI_FC_MASK; + *paad++ = (uint8)(fc & 0xff); + *paad++ = (uint8)((fc >> 8) & 0xff); + + bcopy((uchar *)&h->a1, paad, 2*ETHER_ADDR_LEN); + paad += 2*ETHER_ADDR_LEN; + + seq = ltoh16_ua(&(h->seq)); + seq &= FRAGNUM_MASK; + + *paad++ = (uint8)(seq & 0xff); + *paad++ = (uint8)((seq >> 8) & 0xff); + + bcopy((uchar *)&h->a3, paad, ETHER_ADDR_LEN); + paad += ETHER_ADDR_LEN; + + if (wds) { + bcopy((uchar *)&h->a4, paad, ETHER_ADDR_LEN); + } + /* A4 for the MIC, even when there is no A4 in the packet */ + paad += ETHER_ADDR_LEN; + + if (qos_len) { + *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len]; + *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len + 1]; + } + + *paad++ = iv_data->key_idx; + *paad++ = iv_data->reserved; + + *paad++ = ((data_len - header_len - SMS4_WPI_CBC_MAC_LEN) >> 8) & 0xff; + *paad++ = (data_len - header_len - SMS4_WPI_CBC_MAC_LEN) & 0xff; + + /* length of AAD */ + aad_len = SMS4_WPI_MIN_AAD_LEN + qos_len; + + for (k = 0; k < SMS4_BLOCK_SZ; k++) + tmp[SMS4_BLOCK_SZ-(k+1)] = (iv_data->PN)[k]; + + /* calculate MAC */ + if (sms4_wpi_cbc_mac(ick, tmp, aad_len, aad, p + header_len)) + return (SMS4_WPI_ENCRYPT_ERROR); + + /* encrypt data */ + if (sms4_ofb_crypt(ek, tmp, data_len - header_len, p + header_len)) + return (SMS4_WPI_ENCRYPT_ERROR); + + return (SMS4_WPI_SUCCESS); +} + +/* SMS4-WPI mode decryption of 802.11 packet + * - constructs aad and pn from provided frame + * - calls sms4_ofb_crypt() to decrypt frame + * - calls sms4_wpi_cbc_mac() to compute MAC + * - decrypts in place + * - data_len includes 802.11 header and CBC-MAC MAC + * - returns SMS4_WPI_DECRYPT_ERROR on general error + */ +int +sms4_wpi_pkt_decrypt(const uint8 *ek, + const uint8 *ick, + const size_t data_len, + uint8 *p) +{ + uint8 aad[SMS4_WPI_MAX_AAD_LEN]; + uint8 MAC[SMS4_WPI_CBC_MAC_LEN]; + uint8 *paad = aad; + struct dot11_header *h = (struct dot11_header *)p; + struct wpi_iv *iv_data; + uint16 fc, seq; + uint header_len, aad_len, qos_len = 0, hdr_add_len = 0; + bool wds = FALSE; + uint8 tmp[SMS4_BLOCK_SZ]; + int k; + + bzero(aad, SMS4_WPI_MAX_AAD_LEN); + + fc = ltoh16_ua(&(h->fc)); + + /* WPI only supports protection of DATA frames */ + if (FC_TYPE(fc) != FC_TYPE_DATA) + return (SMS4_WPI_DECRYPT_ERROR); + + /* frame must have Protected flag set */ + if (!(fc & FC_WEP)) + return (SMS4_WPI_DECRYPT_ERROR); + + /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */ + if ((FC_SUBTYPE(fc) & FC_SUBTYPE_QOS_DATA)) + qos_len += 2; + + /* length of A4, if using wds frames */ + wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS)); + if (wds) + hdr_add_len += ETHER_ADDR_LEN; + + /* length of MPDU header, including PN */ + header_len = DOT11_A3_HDR_LEN + SMS4_WPI_IV_LEN + hdr_add_len + qos_len; + + /* pointer to IV */ + iv_data = (struct wpi_iv *)(p + DOT11_A3_HDR_LEN + qos_len + hdr_add_len); + + /* Payload must be > 0 bytes plus MAC */ + if (data_len <= (header_len + SMS4_WPI_CBC_MAC_LEN)) + return (SMS4_WPI_DECRYPT_ERROR); + + /* aad: maskedFC || A1 || A2 || maskedSC || A3 || A4 || KeyIdx || Reserved || L */ + + fc &= SMS4_WPI_FC_MASK; + *paad++ = (uint8)(fc & 0xff); + *paad++ = (uint8)((fc >> 8) & 0xff); + + bcopy((uchar *)&h->a1, paad, 2*ETHER_ADDR_LEN); + paad += 2*ETHER_ADDR_LEN; + + seq = ltoh16_ua(&(h->seq)); + seq &= FRAGNUM_MASK; + + *paad++ = (uint8)(seq & 0xff); + *paad++ = (uint8)((seq >> 8) & 0xff); + + bcopy((uchar *)&h->a3, paad, ETHER_ADDR_LEN); + paad += ETHER_ADDR_LEN; + + if (wds) { + bcopy((uchar *)&h->a4, paad, ETHER_ADDR_LEN); + } + /* A4 for the MIC, even when there is no A4 in the packet */ + paad += ETHER_ADDR_LEN; + + if (qos_len) { + *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len]; + *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len + 1]; + } + + *paad++ = iv_data->key_idx; + *paad++ = iv_data->reserved; + + *paad++ = ((data_len - header_len - SMS4_WPI_CBC_MAC_LEN) >> 8) & 0xff; + *paad++ = (data_len - header_len - SMS4_WPI_CBC_MAC_LEN) & 0xff; + + /* length of AAD */ + aad_len = SMS4_WPI_MIN_AAD_LEN + qos_len; + + for (k = 0; k < SMS4_BLOCK_SZ; k++) + tmp[SMS4_BLOCK_SZ-(k+1)] = (iv_data->PN)[k]; + + /* decrypt data */ + if (sms4_ofb_crypt(ek, tmp, data_len - header_len, + p + header_len)) + return (SMS4_WPI_DECRYPT_ERROR); + + /* store MAC */ + bcopy(p + data_len - SMS4_WPI_CBC_MAC_LEN, MAC, SMS4_WPI_CBC_MAC_LEN); + + /* calculate MAC */ + if (sms4_wpi_cbc_mac(ick, tmp, aad_len, aad, p + header_len)) + return (SMS4_WPI_DECRYPT_ERROR); + + /* compare MAC */ + if (bcmp(p + data_len - SMS4_WPI_CBC_MAC_LEN, MAC, SMS4_WPI_CBC_MAC_LEN)) + return (SMS4_WPI_CBC_MAC_ERROR); + + return (SMS4_WPI_SUCCESS); +} + +#ifdef BCMSMS4_TEST +#include +#include + +#ifdef BCMSMS4_TEST_EMBED + +/* Number of iterations is sensitive to the state of the test vectors since + * encrypt and decrypt are done in place + */ +#define SMS4_TIMING_ITER 100 +#define dbg(args) +#define pres(label, len, data) + +/* returns current time in msec */ +static void +get_time(uint *t) +{ + *t = hndrte_time(); +} + +#else +#ifdef BCMDRIVER + +/* Number of iterations is sensitive to the state of the test vectors since + * encrypt and decrypt are done in place + */ +#define SMS4_TIMING_ITER 1000 +#define dbg(args) printk args +#define pres(label, len, data) + +/* returns current time in msec */ +static void +get_time(uint *t) +{ + *t = jiffies_to_msecs(jiffies); +} + +#else + +#define SMS4_TIMING_ITER 10000 +#include +#define dbg(args) printf args + +#include + +/* returns current time in msec */ +static void +get_time(uint *t) +{ + struct timeval ts; + gettimeofday(&ts, NULL); + *t = ts.tv_sec * 1000 + ts.tv_usec / 1000; +} + +void +pres(const char *label, const size_t len, const uint8 *data) +{ + int k; + printf("%s\n", label); + for (k = 0; k < len; k++) { + printf("0x%02x, ", data[k]); + if (!((k + 1) % (SMS4_BLOCK_SZ/2))) + printf("\n"); + } + printf("\n"); +} +#endif /* BCMDRIVER */ +#endif /* BCMSMS4_TEST_EMBED */ + +int +sms4_test_enc_dec() +{ + uint tstart, tend; + int i, j, k, fail = 0; + uint32 RK[32]; + uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS]; + + for (k = 0; k < NUM_SMS4_VECTORS; k++) { + /* Note that the algorithm spec example output lists X[0] - + * X[32], but those should really be labelled X[4] - X[35] + * (they're the round output, not the input) + */ + + dbg(("sms4_test_enc_dec: Instance %d:\n", k + 1)); + dbg(("sms4_test_enc_dec: Plain Text:\n")); + for (i = 0; i < SMS4_BLOCK_WORDS; i++) + dbg(("sms4_test_enc_dec: PlainText[%02d] = 0x%08x\n", + i, sms4_vec[k].input[i])); + + dbg(("sms4_test_enc_dec: Encryption Master Key:\n")); + for (i = 0; i < SMS4_BLOCK_WORDS; i++) + dbg(("sms4_test_enc_dec: MK[%02d] = 0x%08x\n", + i, sms4_vec[k].key[i])); + + sms4_key_exp(sms4_vec[k].key, RK); + dbg(("sms4_test_enc_dec: Round Key:\n")); + for (i = 0; i < SMS4_RK_WORDS; i++) + dbg(("sms4_test_enc_dec: rk[%02d] = 0x%08x\n", + i, RK[i])); + + for (j = 0; j < SMS4_BLOCK_WORDS; j++) + Y[j] = sms4_vec[k].input[j]; + get_time(&tstart); + for (i = 0; i < *sms4_vec[k].niter; i++) { + for (j = 0; j < SMS4_BLOCK_WORDS; j++) + X[j] = Y[j]; + sms4_enc(Y, X, RK); + } + get_time(&tend); + dbg(("sms4_test_enc_dec: Cipher Text:\n")); + for (i = 0; i < SMS4_BLOCK_WORDS; i++) + dbg(("sms4_test_enc_dec: CipherText[%02d] = 0x%08x\n", + i, Y[i])); + dbg(("sms4_test_enc_dec: Time for Instance %d Encrypt: %d msec\n", + k + 1, tend - tstart)); + for (j = 0; j < SMS4_BLOCK_WORDS; j++) { + if (Y[j] != sms4_vec[k].ref[j]) { + dbg(("sms4_test_enc_dec: sms4_enc failed\n")); + fail++; + } + } + + for (j = 0; j < SMS4_BLOCK_WORDS; j++) + X[j] = sms4_vec[k].ref[j]; + get_time(&tstart); + for (i = 0; i < *sms4_vec[k].niter; i++) { + for (j = 0; j < SMS4_BLOCK_WORDS; j++) + X[j] = Y[j]; + sms4_dec(Y, X, RK); + } + get_time(&tend); + dbg(("sms4_test_enc_dec: Decrypted Plain Text:\n")); + for (i = 0; i < SMS4_BLOCK_WORDS; i++) + dbg(("sms4_test_enc_dec: PlainText[%02d] = 0x%08x\n", i, Y[i])); + dbg(("sms4_test_enc_dec: Time for Instance %d Decrypt: %d msec\n", + k + 1, tend - tstart)); + for (j = 0; j < SMS4_BLOCK_WORDS; j++) { + if (Y[j] != sms4_vec[k].input[j]) { + dbg(("sms4_test_enc_dec: sms4_dec failed\n")); + fail++; + } + } + + dbg(("\n")); + } + + return (fail); +} + +int +sms4_test_cbc_mac() +{ + int retv, k, fail = 0; + + uint8 mac[SMS4_WPI_CBC_MAC_LEN]; + + for (k = 0; k < NUM_SMS4_CBC_MAC_VECTORS; k++) { + dbg(("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC vector %d\n", k)); + retv = sms4_cbc_mac(sms4_cbc_mac_vec[k].ick, + sms4_cbc_mac_vec[k].pn, + sms4_cbc_mac_vec[k].al, + sms4_cbc_mac_vec[k].input, + mac); + if (retv) { + dbg(("sms4_test_cbc_mac: sms4_wpi_cbc_mac of vector %d returned error %d\n", + k, retv)); + fail++; + } + + pres("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC computed: ", SMS4_WPI_CBC_MAC_LEN, + mac); + pres("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC reference: ", SMS4_WPI_CBC_MAC_LEN, + sms4_cbc_mac_vec[k].ref); + + if (bcmp(mac, sms4_cbc_mac_vec[k].ref, SMS4_WPI_CBC_MAC_LEN) != 0) { + dbg(("sms4_test_cbc_mac: sms4_wpi_cbc_mac of vector %d" + " reference mismatch\n", k)); + fail++; + } + } + + dbg(("\n")); + return (fail); +} + +int +sms4_test_ofb_crypt() +{ + int retv, k, fail = 0; + + for (k = 0; k < NUM_SMS4_OFB_VECTORS; k++) { + dbg(("sms4_test_ofb_crypt: SMS4-OFB vector %d\n", k)); + retv = sms4_ofb_crypt(sms4_ofb_vec[k].ek, + sms4_ofb_vec[k].pn, + sms4_ofb_vec[k].il, + sms4_ofb_vec[k].input); + if (retv) { + dbg(("sms4_test_ofb_crypt: encrypt of vector %d returned error %d\n", + k, retv)); + fail++; + } + + pres("sms4_test_ofb_crypt: SMS4-OFB ctxt: ", + sms4_ofb_vec[k].il, sms4_ofb_vec[k].input); + + pres("sms4_test_ofb_crypt: SMS4-OFB ref: ", + sms4_ofb_vec[k].il, sms4_ofb_vec[k].ref); + + if (bcmp(sms4_ofb_vec[k].input, sms4_ofb_vec[k].ref, + sms4_ofb_vec[k].il) != 0) { + dbg(("sms4_test_ofb_crypt: sms4_ofb_crypt of vector %d" + " reference mismatch\n", k)); + fail++; + } + + /* Run again to decrypt and restore vector */ + retv = sms4_ofb_crypt(sms4_ofb_vec[k].ek, + sms4_ofb_vec[k].pn, + sms4_ofb_vec[k].il, + sms4_ofb_vec[k].input); + if (retv) { + dbg(("sms4_test_ofb_crypt: decrypt of vector %d returned error %d\n", + k, retv)); + fail++; + } + } + + dbg(("\n")); + return (fail); +} + +int +sms4_test_wpi_pkt_encrypt_decrypt_timing(int *t) +{ + uint tstart, tend; + int retv, j, k, fail = 0; + + *t = 0; + + for (k = 0; k < NUM_SMS4_WPI_TIMING_VECTORS; k++) { + dbg(("sms4_test_wpi_pkt_encrypt_decrypt_timing: timing SMS4-WPI vector %d\n", k)); + get_time(&tstart); + for (j = 0; j < SMS4_TIMING_ITER; j++) { + retv = sms4_wpi_pkt_encrypt(sms4_wpi_tpkt_vec[k].ek, + sms4_wpi_tpkt_vec[k].ick, + sms4_wpi_tpkt_vec[k].il, + sms4_wpi_tpkt_vec[k].input); + if (retv) { + fail++; + } + + retv = sms4_wpi_pkt_decrypt(sms4_wpi_tpkt_vec[k].ek, + sms4_wpi_tpkt_vec[k].ick, + sms4_wpi_tpkt_vec[k].il, + sms4_wpi_tpkt_vec[k].input); + if (retv) { + fail++; + } + } + + get_time(&tend); + + dbg(("sms4_test_wpi_pkt_encrypt_decrypt_timing: Time for %d iterations of SMS4-WPI " + " vector %d (total MPDU length %d): %d msec\n", + SMS4_TIMING_ITER, k, sms4_wpi_tpkt_vec[k].il, tend - tstart)); + + *t += tend - tstart; + + } + + return (fail); +} + +int +sms4_test_wpi_pkt_encrypt() +{ + int retv, k, fail = 0; + + for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) { + dbg(("sms4_test_wpi_pkt_encrypt: SMS4-WPI packet vector %d\n", k)); + pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ptxt: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + + retv = sms4_wpi_pkt_encrypt(sms4_wpi_pkt_vec[k].ek, + sms4_wpi_pkt_vec[k].ick, + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + if (retv) { + dbg(("sms4_test_wpi_pkt_encrypt: sms4_wpi_pkt_encrypt of vector %d" + " returned error %d\n", k, retv)); + fail++; + } + + pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ctxt: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + + pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ref: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].ref); + + if (bcmp(sms4_wpi_pkt_vec[k].input, sms4_wpi_pkt_vec[k].ref, + sms4_wpi_pkt_vec[k].il) != 0) { + dbg(("sms4_test_wpi_pkt_encrypt: sms4_wpi_pkt_encrypt of vector %d" + " reference mismatch\n", k)); + fail++; + } + } + + dbg(("\n")); + return (fail); +} + +int +sms4_test_wpi_pkt_decrypt() +{ + int retv, k, fail = 0; + + for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) { + dbg(("sms4_test_wpi_pkt_decrypt: SMS4-WPI packet vector %d\n", k)); + pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ctxt: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + + pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ref: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].ref); + + retv = sms4_wpi_pkt_decrypt(sms4_wpi_pkt_vec[k].ek, + sms4_wpi_pkt_vec[k].ick, + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + if (retv) { + dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d" + " returned error %d\n", k, retv)); + fail++; + } + + pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ptxt: ", + sms4_wpi_pkt_vec[k].il, + sms4_wpi_pkt_vec[k].input); + } + + dbg(("\n")); + return (fail); +} + +int +sms4_test_wpi_pkt_micfail() +{ + int retv, k, fail = 0; + uint8 *pkt; + + for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) { + /* copy the reference data, with an error in the last byte */ + pkt = malloc(sms4_wpi_pkt_vec[k].il); + if (pkt == NULL) { + dbg(("%s: out of memory\n", __FUNCTION__)); + fail++; + return (fail); + } + + bcopy(sms4_wpi_pkt_vec[k].ref, pkt, sms4_wpi_pkt_vec[k].il); + + /* create an error in the last byte of the MIC */ + pkt[sms4_wpi_pkt_vec[k].il - 1]++; + + /* decrypt */ + dbg(("sms4_test_wpi_pkt_decrypt: SMS4-WPI packet vector %d\n", k)); + retv = sms4_wpi_pkt_decrypt(sms4_wpi_pkt_vec[k].ek, + sms4_wpi_pkt_vec[k].ick, + sms4_wpi_pkt_vec[k].il, + pkt); + if (!retv) { + dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d" + " did not return expected error %d\n", k, retv)); + fail++; + } + + free(pkt); + } + + dbg(("\n")); + return (fail); +} + +int +sms4_test(int *t) +{ + int fail = 0; + + *t = 0; + +#ifndef BCMSMS4_TEST_EMBED + fail += sms4_test_enc_dec(); + fail += sms4_test_cbc_mac(); + fail += sms4_test_ofb_crypt(); +#endif + + /* since encrypt and decrypt are done in place, and these + * functions use the same vectors, the tests must be run in order + */ + fail += sms4_test_wpi_pkt_encrypt(); + fail += sms4_test_wpi_pkt_decrypt(); + fail += sms4_test_wpi_pkt_micfail(); + + fail += sms4_test_wpi_pkt_encrypt_decrypt_timing(t); + + return (fail); +} + +#ifdef BCMSMS4_TEST_STANDALONE +int +main(int argc, char **argv) +{ + int fail = 0, t; + + fail += sms4_test(&t); + + dbg(("%s: timing result: %d msec\n", __FUNCTION__, t)); + fprintf(stderr, "%s: %s\n", *argv, fail ? "FAILED" : "PASSED"); + return (fail); + +} +#endif /* BCMSMS4_TEST_STANDALONE */ + +#endif /* BCMSMS4_TEST */ + +#endif /* BCMWAPI_WPI */ diff --git a/release/src-rt/bcmcrypto/tkhash.c b/release/src-rt/bcmcrypto/tkhash.c new file mode 100755 index 0000000000..a58ee83238 --- /dev/null +++ b/release/src-rt/bcmcrypto/tkhash.c @@ -0,0 +1,301 @@ +/* + * tkhash.c + * Trimmed version of reference code from "Simple Security Network (SSN) for + * IEEE 802.11", v0.20, plus test routine. + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: tkhash.c,v 1.11 2009-10-21 19:17:20 Exp $ + */ + +/* Reference code from: + * + * Contents: Generate 802.11 per-packet RC4 key hash test vectors + * Date: April 19, 2002 + * Authors: Doug Whiting, Hifn + * Russ Housley, RSA Labs + * Niels Ferguson, MacFergus + * Doug Smith, Cisco + * Notes: + * + * This code is released to the public domain use, built solely out of + * the goodness of our hearts for the benefit of all mankind. As such, + * there are no warranties of any kind given on the correctness or + * usefulness of this code. + * + * This code is written for pedagogical purposes, NOT for performance. + * + */ + +#include + +/* macros for extraction/creation of byte/u16b values */ +#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) +#define Lo8(v16) ((uint8)((v16) & 0x00FF)) +#define Hi8(v16) ((uint8)(((v16) >> 8) & 0x00FF)) +#define Lo16(v32) ((uint16)((v32) & 0xFFFF)) +#define Hi16(v32) ((uint16)(((v32) >>16) & 0xFFFF)) +#define Mk16(hi, lo) ((lo) ^ (((uint16)(hi)) << 8)) + +/* select the Nth 16-bit word of the temporal key byte array TK[] */ +#define TK16(N) Mk16(TK[2 * (N) + 1], TK[2 * (N)]) + +/* fixed algorithm "parameters" */ +#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ +#define TA_SIZE 6 /* 48-bit transmitter address */ +#define TK_SIZE 16 /* 128-bit temporal key */ +#define P1K_SIZE 10 /* 80-bit Phase1 key */ +#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ + +/* + * Note that the Sbox[] table below is a subset of rijndael-alg-fst.c's Te0[256] array. + * To save 1024 bytes of memory, define SHARE_RIJNDAEL_SBOX to re-use that one here. + * Can only be used if rijndael-alg-fst.c is included in the build. + */ +#ifdef SHARE_RIJNDAEL_SBOX + +extern const uint32 rijndaelTe0[256]; + +#define SBOX0(ind) (((rijndaelTe0[ind] >> 16) & 0xff00) | \ + ((rijndaelTe0[ind] >> 0) & 0x00ff)) +#define SBOX1(ind) (((rijndaelTe0[ind] >> 24) & 0x00ff) | \ + ((rijndaelTe0[ind] << 8) & 0xff00)) + +#else /* !SHARE_RIJNDAEL_SBOX */ + +/* 2-byte by 2-byte subset of the full AES S-box table */ +static const uint16 Sbox[2][256] = /* Sbox for hash (can be in ROM) */ +{ + { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A + }, + + { /* second half of table is byte-reversed version of first! */ + 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, + 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, + 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, + 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, + 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, + 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, + 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, + 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, + 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, + 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, + 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, + 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, + 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, + 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, + 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, + 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, + 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, + 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, + 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, + 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, + 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, + 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, + 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, + 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, + 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, + 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, + 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, + 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, + 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, + 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, + 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, + 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C + } +}; + +#define SBOX0(ind) Sbox[0][ind] +#define SBOX1(ind) Sbox[1][ind] + +#endif /* !SHARE_RIJNDAEL_SBOX */ + +/* S-box lookup: 16 bits --> 16 bits */ +#define _S_(v16) (SBOX0(Lo8(v16)) ^ SBOX1(Hi8(v16))) + +/* + * Routine: Phase 1 -- generate P1K, given TA, TK, IV32 + * + * Inputs: + * TK[] = temporal key [128 bits] + * TA[] = transmitter's MAC address [ 48 bits] + * IV32 = upper 32 bits of IV [ 32 bits] + * Output: + * P1K[] = Phase 1 key [ 80 bits] + * + * Note: + * This function only needs to be called every 2**16 packets, + * although in theory it could be called every packet. + * + */ +void +BCMROMFN(tkhash_phase1)(uint16 *P1K, const uint8 *TK, const uint8 *TA, uint32 IV32) +{ + uint16 i; + + /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ + P1K[0] = Lo16(IV32); + P1K[1] = Hi16(IV32); + P1K[2] = Mk16(TA[1], TA[0]); /* use TA[] as little-endian */ + P1K[3] = Mk16(TA[3], TA[2]); + P1K[4] = Mk16(TA[5], TA[4]); + + /* Now compute an unbalanced Feistel cipher with 80-bit block */ + /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ + for (i = 0; i < PHASE1_LOOP_CNT; i++) { + /* Each add operation here is mod 2**16 */ + P1K[0] += _S_(P1K[4] ^ TK16((i & 1) + 0)); + P1K[1] += _S_(P1K[0] ^ TK16((i & 1) + 2)); + P1K[2] += _S_(P1K[1] ^ TK16((i & 1) + 4)); + P1K[3] += _S_(P1K[2] ^ TK16((i & 1) + 6)); + P1K[4] += _S_(P1K[3] ^ TK16((i & 1) + 0)); + P1K[4] += i; /* avoid "slide attacks" */ + } +} + +/* + * + * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 + * + * Inputs: + * TK[] = Temporal key [128 bits] + * P1K[] = Phase 1 output key [ 80 bits] + * IV16 = low 16 bits of IV counter [ 16 bits] + * Output: + * RC4KEY[] = the key used to encrypt the packet [128 bits] + * + * Note: + * The value {TA,IV32,IV16} for Phase1/Phase2 must be unique + * across all packets using the same key TK value. Then, for a + * given value of TK[], this TKIP48 construction guarantees that + * the final RC4KEY value is unique across all packets. + * + * Suggested implementation optimization: if PPK[] is "overlaid" + * appropriately on RC4KEY[], there is no need for the final + * for loop below that copies the PPK[] result into RC4KEY[]. + * + */ +void +BCMROMFN(tkhash_phase2)(uint8 *RC4KEY, const uint8 *TK, const uint16 *P1K, uint16 IV16) +{ + uint16 i; + uint16 PPK[6]; /* temporary key for mixing */ + + /* Note: all adds in the PPK[] equations below are mod 2**16 */ + for (i = 0; i < 5; i++) PPK[i]=P1K[i]; /* first, copy P1K to PPK */ + PPK[5] = P1K[4] + IV16; /* next, add in IV16 */ + + /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ + PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ + PPK[1] += _S_(PPK[0] ^ TK16(1)); + PPK[2] += _S_(PPK[1] ^ TK16(2)); + PPK[3] += _S_(PPK[2] ^ TK16(3)); + PPK[4] += _S_(PPK[3] ^ TK16(4)); + PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ + + /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ + PPK[0] += RotR1(PPK[5] ^ TK16(6)); + PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ + PPK[2] += RotR1(PPK[1]); + PPK[3] += RotR1(PPK[2]); + PPK[4] += RotR1(PPK[3]); + PPK[5] += RotR1(PPK[4]); + /* Note: At this point, for a given key TK[0..15], the 96-bit output */ + /* value PPK[0..5] is guaranteed to be unique, as a function */ + /* of the 96-bit "input" value {TA,IV32,IV16}. That is, P1K */ + /* is now a keyed permutation of {TA,IV32,IV16}. */ + + /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ + RC4KEY[0] = Hi8(IV16); /* RC4KEY[0..2] is the WEP IV */ + RC4KEY[1] =(Hi8(IV16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ + RC4KEY[2] = Lo8(IV16); + RC4KEY[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); + + /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ + for (i = 0; i < 6; i++) { + RC4KEY[4 + 2 * i] = Lo8(PPK[i]); + RC4KEY[5 + 2 * i] = Hi8(PPK[i]); + } +} + + +#ifdef BCMTKHASH_TEST +#include + +#if defined(__GNUC__) +#include +#endif + +#include "tkhash_vectors.h" +#define NUM_VECTORS (sizeof(tkhash_vec)/sizeof(tkhash_vec[0])) + +int main(int argc, char **argv) +{ + int k, fail = 0; + uint16 p1k[TKHASH_P1_KEY_SIZE / 2]; + uint8 rc4key[TKHASH_P2_KEY_SIZE]; + for (k = 0; k < NUM_VECTORS; k++) { + tkhash_phase1(p1k, tkhash_vec[k].tk, tkhash_vec[k].ta, + *(tkhash_vec[k].iv32)); + + if (bcmp(p1k, tkhash_vec[k].p1k, TKHASH_P1_KEY_SIZE) != 0) { + printf("%s: TKHash Phase1 %d failed\n", *argv, k); + fail++; + } else { + printf("%s: TKHash Phase1 %d passed\n", *argv, k); + } + + tkhash_phase2(rc4key, tkhash_vec[k].tk, p1k, + *(tkhash_vec[k].iv16)); + + if (bcmp(rc4key, tkhash_vec[k].rc4key, TKHASH_P2_KEY_SIZE) != 0) { + printf("%s: TKHash Phase2 %d failed\n", *argv, k); + fail++; + } else { + printf("%s: TKHash Phase2 %d passed\n", *argv, k); + } + + } + + printf("%s: %s\n", *argv, fail?"FAILED":"PASSED"); + return (fail); +} +#endif /* BCMTKHASH_TEST */ diff --git a/release/src-rt/bcmcrypto/tkhash_vectors.h b/release/src-rt/bcmcrypto/tkhash_vectors.h new file mode 100755 index 0000000000..ad53e9d29e --- /dev/null +++ b/release/src-rt/bcmcrypto/tkhash_vectors.h @@ -0,0 +1,171 @@ +/* + * tkhash_vectors.h + * TKIP Key Hash test vectors + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: tkhash_vectors.h,v 1.3 2006-06-14 21:08:49 Exp $ + */ + +#include + +/* From 802.11i-D3.0 */ +uint8 tk_00[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ta_00[] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 }; + +uint32 iv32_00 = 0x00000000; + +uint16 iv16_00 = 0x0000; + +uint16 p1k_00[] = { 0x3DD2, 0x016E, 0x76F4, 0x8697, 0xB2E8 }; + +uint8 rc4key_00 [] = { + 0x00, 0x20, 0x00, 0x33, 0xEA, 0x8D, 0x2F, 0x60, + 0xCA, 0x6D, 0x13, 0x74, 0x23, 0x4A, 0x66, 0x0B + }; + + +uint8 tk_01[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + +uint8 ta_01[] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 }; + +uint32 iv32_01 = 0x00000000; + +uint16 iv16_01 = 0x0001; + +uint16 p1k_01[] = { 0x3DD2, 0x016E, 0x76F4, 0x8697, 0xB2E8 }; + +uint8 rc4key_01[] = { + 0x00, 0x20, 0x01, 0x90, 0xFF, 0xDC, 0x31, 0x43, + 0x89, 0xA9, 0xD9, 0xD0, 0x74, 0xFD, 0x20, 0xAA + }; + + +uint8 tk_02[] = { + 0x63, 0x89, 0x3B, 0x25, 0x08, 0x40, 0xB8, 0xAE, + 0x0B, 0xD0, 0xFA, 0x7E, 0x61, 0xD2, 0x78, 0x3E + }; + +uint8 ta_02[] = { 0x64, 0xF2, 0xEA, 0xED, 0xDC, 0x25 }; + +uint32 iv32_02 = 0x20DCFD43; + +uint16 iv16_02 = 0xFFFF; + +uint16 p1k_02[] = { 0x7C67, 0x49D7, 0x9724, 0xB5E9, 0xB4F1 }; + +uint8 rc4key_02[] = { + 0xFF, 0x7F, 0xFF, 0x93, 0x81, 0x0F, 0xC6, 0xE5, + 0x8F, 0x5D, 0xD3, 0x26, 0x25, 0x15, 0x44, 0xCE + }; + + +uint8 tk_03[] = { + 0x63, 0x89, 0x3B, 0x25, 0x08, 0x40, 0xB8, 0xAE, + 0x0B, 0xD0, 0xFA, 0x7E, 0x61, 0xD2, 0x78, 0x3E + }; + +uint8 ta_03[] = { 0x64, 0xF2, 0xEA, 0xED, 0xDC, 0x25 }; + +uint32 iv32_03 = 0x20DCFD44; + +uint16 iv16_03 = 0x0000; + +uint16 p1k_03[] = { 0x5A5D, 0x73A8, 0xA859, 0x2EC1, 0xDC8B }; + +uint8 rc4key_03[] = { + 0x00, 0x20, 0x00, 0x49, 0x8C, 0xA4, 0x71, 0xFC, + 0xFB, 0xFA, 0xA1, 0x6E, 0x36, 0x10, 0xF0, 0x05 + }; + + +uint8 tk_04[] = { + 0x98, 0x3A, 0x16, 0xEF, 0x4F, 0xAC, 0xB3, 0x51, + 0xAA, 0x9E, 0xCC, 0x27, 0x1D, 0x73, 0x09, 0xE2 + }; + +uint8 ta_04[] = { 0x50, 0x9C, 0x4B, 0x17, 0x27, 0xD9 }; + +uint32 iv32_04 = 0xF0A410FC; + +uint16 iv16_04 = 0x058C; + +uint16 p1k_04[] = { 0xF2DF, 0xEBB1, 0x88D3, 0x5923, 0xA07C }; + +uint8 rc4key_04[] = { + 0x05, 0x25, 0x8C, 0xF4, 0xD8, 0x51, 0x52, 0xF4, + 0xD9, 0xAF, 0x1A, 0x64, 0xF1, 0xD0, 0x70, 0x21 + }; + + +uint8 tk_05[] = { + 0x98, 0x3A, 0x16, 0xEF, 0x4F, 0xAC, 0xB3, 0x51, + 0xAA, 0x9E, 0xCC, 0x27, 0x1D, 0x73, 0x09, 0xE2 + }; + +uint8 ta_05[] = { 0x50, 0x9C, 0x4B, 0x17, 0x27, 0xD9 }; + +uint32 iv32_05 = 0xF0A410FC; + +uint16 iv16_05 = 0x058D; + +uint16 p1k_05[] = { 0xF2DF, 0xEBB1, 0x88D3, 0x5923, 0xA07C }; + +uint8 rc4key_05[] = { + 0x05, 0x25, 0x8D, 0x09, 0xF8, 0x15, 0x43, 0xB7, + 0x6A, 0x59, 0x6F, 0xC2, 0xC6, 0x73, 0x8B, 0x30 + }; + + +uint8 tk_06[] = { + 0xC8, 0xAD, 0xC1, 0x6A, 0x8B, 0x4D, 0xDA, 0x3B, + 0x4D, 0xD5, 0xB6, 0x54, 0x38, 0x35, 0x9B, 0x05 + }; + +uint8 ta_06[] = { 0x94, 0x5E, 0x24, 0x4E, 0x4D, 0x6E }; + +uint32 iv32_06 = 0x8B1573B7; + +uint16 iv16_06 = 0x30F8; + +uint16 p1k_06[] = { 0xEFF1, 0x3F38, 0xA364, 0x60A9, 0x76F3 }; + +uint8 rc4key_06[] = { + 0x30, 0x30, 0xF8, 0x65, 0x0D, 0xA0, 0x73, 0xEA, + 0x61, 0x4E, 0xA8, 0xF4, 0x74, 0xEE, 0x03, 0x19 + }; + +typedef struct { + uint8 *tk; + uint8 *ta; + uint32 *iv32; + uint16 *iv16; + uint16 *p1k; + uint8 *rc4key; +} tkhash_vector_t; + +#define TKHASH_VECTOR_ENTRY(x) \ + { tk_##x, ta_##x, &iv32_##x, &iv16_##x, p1k_##x, rc4key_##x } + +tkhash_vector_t tkhash_vec[] = { + TKHASH_VECTOR_ENTRY(00), + TKHASH_VECTOR_ENTRY(01), + TKHASH_VECTOR_ENTRY(02), + TKHASH_VECTOR_ENTRY(03), + TKHASH_VECTOR_ENTRY(04), + TKHASH_VECTOR_ENTRY(05), + TKHASH_VECTOR_ENTRY(06) + }; diff --git a/release/src-rt/bcmcrypto/tkmic.c b/release/src-rt/bcmcrypto/tkmic.c new file mode 100755 index 0000000000..f9f94075dd --- /dev/null +++ b/release/src-rt/bcmcrypto/tkmic.c @@ -0,0 +1,88 @@ +/* + * tkmic.c - TKIP Message Integrity Check (MIC) functions + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: tkmic.c,v 1.2.540.1 2010-04-22 22:27:54 Exp $ + */ + +#include +#include +#include + +/* + * "Michael" Messge Integrity Check (MIC) algorithm + */ +static INLINE void +tkip_micblock(uint32 *left, uint32 *right) +{ + uint32 l = *left; + uint32 r = *right; + + r ^= ROTR32(l, 15); + l += r; /* mod 2^32 */ + r ^= XSWAP32(l); + l += r; /* mod 2^32 */ + r ^= ROTR32(l, 29); + l += r; /* mod 2^32 */ + r ^= ROTR32(l, 2); + l += r; /* mod 2^32 */ + + *left = l; + *right = r; +} + + +/* compute mic across message */ +/* buffer must already have terminator and padding appended */ +/* buffer length (n) specified in bytes */ +void +BCMROMFN(tkip_mic)(uint32 k0, uint32 k1, int n, uint8 *m, uint32 *left, uint32 *right) +{ + uint32 l = k0; + uint32 r = k1; + + if (((uintptr)m & 3) == 0) { + for (; n > 0; n -= 4) { + l ^= ltoh32(*(uint *)m); + m += 4; + tkip_micblock(&l, &r); + } + } else { + for (; n > 0; n -= 4) { + l ^= ltoh32_ua(m); + m += 4; + tkip_micblock(&l, &r); + } + } + *left = l; + *right = r; +} + +/* append the MIC terminator to the data buffer */ +/* terminator is 0x5a followed by 4-7 bytes of 0 */ +/* param 'o' is the current frag's offset in the frame */ +/* returns length of message plus terminator in bytes */ +int +BCMROMFN(tkip_mic_eom)(uint8 *m, uint n, uint o) +{ + uint8 *mend = m + n; + uint t = n + o; + mend[0] = 0x5a; + mend[1] = 0; + mend[2] = 0; + mend[3] = 0; + mend[4] = 0; + mend += 5; + o += n + 5; + while (o++%4) { + *mend++ = 0; + } + return (n+o-1-t); +} diff --git a/release/src-rt/bcmcrypto/wep.c b/release/src-rt/bcmcrypto/wep.c new file mode 100755 index 0000000000..c42c35fdf1 --- /dev/null +++ b/release/src-rt/bcmcrypto/wep.c @@ -0,0 +1,86 @@ +/* + * wep.c - WEP functions + * + * Copyright (C) 2010, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * $Id: wep.c,v 1.4 2007-04-29 04:36:19 Exp $ + */ + +#include + +/* include wl driver config file if this file is compiled for driver */ +#ifdef BCMDRIVER +#include +#else +#if defined(__GNUC__) +extern void bcopy(const void *src, void *dst, int len); +extern int bcmp(const void *b1, const void *b2, int len); +extern void bzero(void *b, int len); +#else +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), 0, (len)) +#endif /* defined(__GNUC__) */ +#endif /* BCMDRIVER */ + +#include +#include +#include +#include + +/* WEP-encrypt a buffer */ +/* assumes a contiguous buffer, with IV prepended, and with enough space at + * the end for the ICV + */ +void +BCMROMFN(wep_encrypt)(uint buf_len, uint8 *buf, uint sec_len, uint8 *sec_data) +{ + uint8 key_data[16]; + uint32 ICV; + rc4_ks_t ks; + uint8 *body = buf + DOT11_IV_LEN; + uint body_len = buf_len - (DOT11_IV_LEN + DOT11_ICV_LEN); + uint8 *picv = body + body_len; + + bcopy(buf, key_data, 3); + bcopy(sec_data, &key_data[3], sec_len); + + prepare_key(key_data, sec_len + 3, &ks); + + /* append ICV */ + ICV = ~hndcrc32(body, body_len, CRC32_INIT_VALUE); + picv[0] = ICV & 0xff; + picv[1] = (ICV >> 8) & 0xff; + picv[2] = (ICV >> 16) & 0xff; + picv[3] = (ICV >> 24) & 0xff; + + rc4(body, body_len + DOT11_ICV_LEN, &ks); +} + +/* WEP-decrypt + * Assumes a contigous buffer, with IV prepended. + * Returns TRUE if ICV check passes, FALSE otherwise + * + */ +bool +BCMROMFN(wep_decrypt)(uint buf_len, uint8 *buf, uint sec_len, uint8 *sec_data) +{ + uint8 key_data[16]; + rc4_ks_t ks; + + bcopy(buf, key_data, 3); + bcopy(sec_data, &key_data[3], sec_len); + + prepare_key(key_data, sec_len + 3, &ks); + + rc4(buf + DOT11_IV_LEN, buf_len - DOT11_IV_LEN, &ks); + + return (hndcrc32(buf + DOT11_IV_LEN, buf_len - DOT11_IV_LEN, CRC32_INIT_VALUE) == + CRC32_GOOD_VALUE); +} diff --git a/release/src-rt/emf/emf/emfc.c b/release/src-rt/emf/emf/emfc.c old mode 100644 new mode 100755 index 22787a097d..e8db9ab982 --- a/release/src-rt/emf/emf/emfc.c +++ b/release/src-rt/emf/emf/emfc.c @@ -34,6 +34,16 @@ #include "emfc.h" #include "emf_export.h" +/* BH-enabled helpers */ +#define EMF_RELOCK(lock) do { \ + OSL_UNLOCK(lock); \ + spin_lock(&((lock)->slock)); \ +} while (0) +#define OSL_RELOCK(lock) do { \ + spin_unlock(&((lock)->slock)); \ + OSL_LOCK(lock); \ +} while (0) + static CLIST_DECL_INIT(emfc_list_head); static osl_lock_t emfc_list_lock; @@ -187,6 +197,8 @@ emfc_unreg_frame_handle(emfc_info_t *emfc, void *sdu, void *ifp, uint8 proto, /* Flood the frame on to user specified ports */ for (ptr = emfc->iflist_head; ptr != NULL; ptr = ptr->next) { + int32 res; + /* Dont forward the frame on to the port on which it * was received. */ @@ -216,8 +228,11 @@ emfc_unreg_frame_handle(emfc_info_t *emfc, void *sdu, void *ifp, uint8 proto, return (EMF_DROP); } - if (emfc->wrapper.forward_fn(emfc->emfi, sdu_clone, dest_ip, - ptr->ifp, rt_port) != SUCCESS) + EMF_RELOCK(emfc->iflist_lock); + res = emfc->wrapper.forward_fn(emfc->emfi, sdu_clone, dest_ip, + ptr->ifp, rt_port); + OSL_RELOCK(emfc->iflist_lock); + if (res != SUCCESS) { EMF_INFO("Unable to flood the unreg frame on to %s\n", DEV_IFNAME(ptr->ifp)); @@ -346,6 +361,7 @@ emfc_input(emfc_info_t *emfc, void *sdu, void *ifp, uint8 *iph, bool rt_port) emfc_mgrp_t *mgrp; emfc_mi_t *mi; void *sdu_clone; + int32 res; EMF_DEBUG("Received frame with proto %d\n", IPV4_PROT(iph)); @@ -397,7 +413,9 @@ emfc_input(emfc_info_t *emfc, void *sdu, void *ifp, uint8 *iph, bool rt_port) return (EMF_DROP); } + EMF_RELOCK(emfc->fdb_lock); emfc->wrapper.sendup_fn(emfc->emfi, sdu_clone); + OSL_RELOCK(emfc->fdb_lock); EMFC_STATS_INCR(emfc, mcast_data_sentup); } @@ -424,9 +442,11 @@ emfc_input(emfc_info_t *emfc, void *sdu, void *ifp, uint8 *iph, bool rt_port) return (EMF_DROP); } - emfc->wrapper.forward_fn(emfc->emfi, sdu_clone, - dest_ip, mi->mi_mhif->mhif_ifp, rt_port) ? - EMFC_STATS_INCR(emfc, mcast_data_dropped) : + EMF_RELOCK(emfc->fdb_lock); + res = emfc->wrapper.forward_fn(emfc->emfi, sdu_clone, + dest_ip, mi->mi_mhif->mhif_ifp, rt_port); + OSL_RELOCK(emfc->fdb_lock); + res ? EMFC_STATS_INCR(emfc, mcast_data_dropped) : mi->mi_mhif->mhif_data_fwd++, mi->mi_data_fwd++; } @@ -439,9 +459,11 @@ emfc_input(emfc_info_t *emfc, void *sdu, void *ifp, uint8 *iph, bool rt_port) { EMF_DEBUG("Sending the original packet buffer\n"); - emfc->wrapper.forward_fn(emfc->emfi, sdu, dest_ip, - mi->mi_mhif->mhif_ifp, rt_port) ? - EMFC_STATS_INCR(emfc, mcast_data_dropped) : + EMF_RELOCK(emfc->fdb_lock); + res = emfc->wrapper.forward_fn(emfc->emfi, sdu, dest_ip, + mi->mi_mhif->mhif_ifp, rt_port); + OSL_RELOCK(emfc->fdb_lock); + res ? EMFC_STATS_INCR(emfc, mcast_data_dropped) : mi->mi_mhif->mhif_data_fwd++, mi->mi_data_fwd++; } diff --git a/release/src-rt/emf/emfconf/Makefile b/release/src-rt/emf/emfconf/Makefile old mode 100644 new mode 100755 index d1ad54b05c..b589896bdc --- a/release/src-rt/emf/emfconf/Makefile +++ b/release/src-rt/emf/emfconf/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.3 2008/08/12 17:43:47 Exp $ +# $Id: Makefile 241182 2011-02-17 21:50:03Z gmo $ # CROSS = diff --git a/release/src-rt/emf/emfconf/emfu.c b/release/src-rt/emf/emfconf/emfu.c old mode 100644 new mode 100755 index 04f5976003..6e2c829110 --- a/release/src-rt/emf/emfconf/emfu.c +++ b/release/src-rt/emf/emfconf/emfu.c @@ -3,7 +3,7 @@ * EMF, enable/disable BSS forwarding, add/delete/list the Static * MFDB entries. * - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -11,7 +11,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: emfu.c,v 1.5 2007/10/13 00:54:06 Exp $ + * $Id: emfu.c 241182 2011-02-17 21:50:03Z gmo $ */ #include #include diff --git a/release/src-rt/emf/emfconf/emfu.h b/release/src-rt/emf/emfconf/emfu.h old mode 100644 new mode 100755 index 664c3cfcf4..562ffab5a1 --- a/release/src-rt/emf/emfconf/emfu.h +++ b/release/src-rt/emf/emfconf/emfu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -7,7 +7,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: emfu.h,v 1.3 2007/07/11 23:23:20 Exp $ + * $Id: emfu.h 241182 2011-02-17 21:50:03Z gmo $ */ #ifndef _EMFU_H_ diff --git a/release/src-rt/emf/emfconf/emfu_linux.c b/release/src-rt/emf/emfconf/emfu_linux.c old mode 100644 new mode 100755 index 19809fadc1..3a73450214 --- a/release/src-rt/emf/emfconf/emfu_linux.c +++ b/release/src-rt/emf/emfconf/emfu_linux.c @@ -1,7 +1,7 @@ /* * EMFL Command Line Utility Linux specific code * - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -9,7 +9,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: emfu_linux.c,v 1.1 2007/03/17 03:14:23 Exp $ + * $Id: emfu_linux.c 241182 2011-02-17 21:50:03Z gmo $ */ #include diff --git a/release/src-rt/emf/emfconf/emfu_linux.h b/release/src-rt/emf/emfconf/emfu_linux.h old mode 100644 new mode 100755 index ba44041cdd..570072d356 --- a/release/src-rt/emf/emfconf/emfu_linux.h +++ b/release/src-rt/emf/emfconf/emfu_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -7,7 +7,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: emfu_linux.h,v 1.1 2007/03/17 03:14:23 Exp $ + * $Id: emfu_linux.h 241182 2011-02-17 21:50:03Z gmo $ */ #ifndef _EMFU_LINUX_H_ diff --git a/release/src-rt/emf/igs/igsc.c b/release/src-rt/emf/igs/igsc.c old mode 100644 new mode 100755 index 6fa3553b6b..e34d614e1c --- a/release/src-rt/emf/igs/igsc.c +++ b/release/src-rt/emf/igs/igsc.c @@ -241,21 +241,19 @@ igsc_rtlist_add(igsc_info_t *igsc_info, void *ifp, uint32 mr_ip) static void igsc_rtlist_clear(igsc_info_t *igsc_info) { - clist_head_t *ptr, *tmp; + clist_head_t *ptr; igsc_rtlist_t *rtl_ptr; OSL_LOCK(igsc_info->rtlist_lock); - ptr = igsc_info->rtlist_head.next; - while (ptr != &igsc_info->rtlist_head) + for (ptr = igsc_info->rtlist_head.next; + ptr != &igsc_info->rtlist_head; ptr = ptr->next) { rtl_ptr = clist_entry(ptr, igsc_rtlist_t, list); - tmp = ptr->next; osl_timer_del(rtl_ptr->rtlist_timer); emfc_rtport_del(igsc_info->emf_handle, rtl_ptr->ifp); clist_delete(ptr); MFREE(igsc_info->osh, rtl_ptr, sizeof(igsc_rtlist_t)); - ptr = tmp; } OSL_UNLOCK(igsc_info->rtlist_lock); diff --git a/release/src-rt/emf/igsconf/Makefile b/release/src-rt/emf/igsconf/Makefile old mode 100644 new mode 100755 index b2ae83e64d..aaf9b9abad --- a/release/src-rt/emf/igsconf/Makefile +++ b/release/src-rt/emf/igsconf/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.3 2008/08/12 17:43:48 Exp $ +# $Id: Makefile 241182 2011-02-17 21:50:03Z gmo $ # CROSS = diff --git a/release/src-rt/emf/igsconf/igsu.c b/release/src-rt/emf/igsconf/igsu.c old mode 100644 new mode 100755 index 4e92835c3d..e10b564a8a --- a/release/src-rt/emf/igsconf/igsu.c +++ b/release/src-rt/emf/igsconf/igsu.c @@ -2,7 +2,7 @@ * IGSL Command Line Utility: This utility can be used to add/remove * snooping capability on desired bridge interface. * - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -10,7 +10,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: igsu.c,v 1.5 2007/10/13 00:54:08 Exp $ + * $Id: igsu.c 241182 2011-02-17 21:50:03Z gmo $ */ #include #include diff --git a/release/src-rt/emf/igsconf/igsu.h b/release/src-rt/emf/igsconf/igsu.h old mode 100644 new mode 100755 index 26cd78f105..1d4c5d8b68 --- a/release/src-rt/emf/igsconf/igsu.h +++ b/release/src-rt/emf/igsconf/igsu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -7,7 +7,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: igsu.h,v 1.3 2007/07/11 23:23:32 Exp $ + * $Id: igsu.h 241182 2011-02-17 21:50:03Z gmo $ */ #ifndef _IGSU_H_ diff --git a/release/src-rt/emf/igsconf/igsu_linux.c b/release/src-rt/emf/igsconf/igsu_linux.c old mode 100644 new mode 100755 index 42b31fe0d3..a9f7c021f3 --- a/release/src-rt/emf/igsconf/igsu_linux.c +++ b/release/src-rt/emf/igsconf/igsu_linux.c @@ -1,7 +1,7 @@ /* * IGSL Command Line Utility Linux specific code * - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -9,7 +9,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: igsu_linux.c,v 1.1 2007/03/17 03:15:10 Exp $ + * $Id: igsu_linux.c 241182 2011-02-17 21:50:03Z gmo $ */ #include diff --git a/release/src-rt/emf/igsconf/igsu_linux.h b/release/src-rt/emf/igsconf/igsu_linux.h old mode 100644 new mode 100755 index e24e58c0bd..ce802e3cf1 --- a/release/src-rt/emf/igsconf/igsu_linux.h +++ b/release/src-rt/emf/igsconf/igsu_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Broadcom Corporation + * Copyright (C) 2010, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; @@ -7,7 +7,7 @@ * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. * - * $Id: igsu_linux.h,v 1.1 2007/03/17 03:15:10 Exp $ + * $Id: igsu_linux.h 241182 2011-02-17 21:50:03Z gmo $ */ #ifndef _IGSU_LINUX_H_ diff --git a/release/src-rt/include/UdpLib.h b/release/src-rt/include/UdpLib.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/aidmp.h b/release/src-rt/include/aidmp.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/amemc_core.h b/release/src-rt/include/amemc_core.h new file mode 100755 index 0000000000..5add67d1bd --- /dev/null +++ b/release/src-rt/include/amemc_core.h @@ -0,0 +1,152 @@ +/* + * BCM47XX ARM DDR2/DDR3 memory controlers. + * + * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id$ + */ + +#ifndef _AMEMC_H +#define _AMEMC_H + +#ifdef _LANGUAGE_ASSEMBLY + +#if defined(IL_BIGENDIAN) && defined(BCMHND74K) +/* Swapped defines for big-endian code in 74K based chips */ + +#else /* !IL_BIGENDIAN || !BCMHND74K */ + +/* + * DDR23PHY registers + */ +#define DDR23PHY_PLL_STATUS 0x010 +#define DDR23PHY_PLL_CONFIG 0x014 +#define DDR23PHY_PLL_PRE_DIVIDER 0x018 +#define DDR23PHY_PLL_DIVIDER 0x01c +#define DDR23PHY_STATIC_VDL_OVERRIDE 0x030 +#define DDR23PHY_ZQ_PVT_COMP_CTL 0x03c +#define DDR23PHY_BL3_VDL_CALIBRATE 0x104 +#define DDR23PHY_BL3_VDL_STATUS 0x108 +#define DDR23PHY_BL3_READ_CONTROL 0x130 +#define DDR23PHY_BL3_WR_PREAMBLE_MODE 0x148 +#define DDR23PHY_BL2_VDL_CALIBRATE 0x204 +#define DDR23PHY_BL2_VDL_STATUS 0x208 +#define DDR23PHY_BL2_READ_CONTROL 0x230 +#define DDR23PHY_BL2_WR_PREAMBLE_MODE 0x248 +#define DDR23PHY_BL1_VDL_CALIBRATE 0x304 +#define DDR23PHY_BL1_VDL_STATUS 0x308 +#define DDR23PHY_BL1_READ_CONTROL 0x330 +#define DDR23PHY_BL1_WR_PREAMBLE_MODE 0x348 +#define DDR23PHY_BL0_VDL_CALIBRATE 0x404 +#define DDR23PHY_BL0_VDL_STATUS 0x408 +#define DDR23PHY_BL0_READ_CONTROL 0x430 +#define DDR23PHY_BL0_WR_PREAMBLE_MODE 0x448 + +/* + * PL341 registers + */ +#define PL341_memc_status 0x000 +#define PL341_memc_cmd 0x004 +#define PL341_direct_cmd 0x008 +#define PL341_memory_cfg 0x00c +#define PL341_refresh_prd 0x010 +#define PL341_cas_latency 0x014 +#define PL341_write_latency 0x018 +#define PL341_t_mrd 0x01c +#define PL341_t_ras 0x020 +#define PL341_t_rc 0x024 +#define PL341_t_rcd 0x028 +#define PL341_t_rfc 0x02c +#define PL341_t_rp 0x030 +#define PL341_t_rrd 0x034 +#define PL341_t_wr 0x038 +#define PL341_t_wtr 0x03c +#define PL341_t_xp 0x040 +#define PL341_t_xsr 0x044 +#define PL341_t_esr 0x048 +#define PL341_memory_cfg2 0x04c +#define PL341_memory_cfg3 0x050 +#define PL341_t_faw 0x054 +#define PL341_chip_0_cfg 0x200 +#define PL341_user_config0 0x304 + +#endif /* IL_BIGENDIAN && BCMHND74K */ + +#endif /* _LANGUAGE_ASSEMBLY */ + +#define MEMC_BURST_LENGTH (4) + +#define AI_DDRPHY_BASE (0x1800f000) + +/* Default configuration from bsp_config.h of _BCM953003RSP_ */ +/* (required) PLL clock */ +#define CFG_DDR_PLL_CLOCK (331250) /* KHz */ + +/* (required) CAS Latency (NOTE: could be affected by PLL clock) */ +#define CFG_DDR_CAS_LATENCY 5 + +/* (required) t_wr (picoseconds) */ +#define CFG_DDR_T_WR 15000 + +/* (optional) Refresh period t_refi (picoseconds) */ +#define CFG_DDR_REFRESH_PRD 7800000 + +/* (optional) t_rfc (picoseconds) */ +#define CFG_DDR_T_RFC 105000 + +/* + * Convenient macros + */ +#define MEMCYCLES(psec) (((psec) * (CFG_DDR_PLL_CLOCK) + 999999999) / 1000000000) + +/* + * Convenient macros (minimum requirement and truncated decimal) + */ +#define MEMCYCLES_MIN(psec) ((psec) * (CFG_DDR_PLL_CLOCK) / 1000000000) + +/* + * PLL clock configuration + */ +#define PLL_NDIV_INT_VAL (16 * (CFG_DDR_PLL_CLOCK) / 100000) + +/* + * Values for PL341 Direct Command Register + */ +#define MCHIP_CMD_PRECHARGE_ALL (0x0 << 18) +#define MCHIP_CMD_AUTO_REFRESH (0x1 << 18) +#define MCHIP_CMD_MODE_REG (0x2 << 18) +#define MCHIP_CMD_NOP (0x3 << 18) +#define MCHIP_MODEREG_SEL(x) ((x) << 16) +#define MCHIP_MR_WRITE_RECOVERY(x) (((x) - 1) << 9) +#define MCHIP_MR_DLL_RESET(x) ((x) << 8) +#define MCHIP_MR_CAS_LATENCY(x) ((x) << 4) +#if (MEMC_BURST_LENGTH == 4) +#define MCHIP_MR_BURST_LENGTH (2) +#else +#define MCHIP_MR_BURST_LENGTH (3) +#endif +#define MCHIP_EMR1_DLL_DISABLE(x) ((x) << 0) +#define MCHIP_EMR1_RTT_ODT_DISABLED (0) +#define MCHIP_EMR1_RTT_75_OHM (1 << 2) +#define MCHIP_EMR1_RTT_150_OHM (1 << 6) +#define MCHIP_EMR1_RTT_50_OHM ((1 << 6) | (1 << 2)) +#define MCHIP_EMR1_OCD_CALI_EXIT (0x0 << 7) +#define MCHIP_EMR1_OCD_CALI_DEFAULT (0x3 << 7) + +/* PVT calibration */ +#define PVT_MAX_RETRY (120) +#define PVT_MATCHED_COUNT (3) + +#endif /* _AMEMC_H */ diff --git a/release/src-rt/include/arminc.h b/release/src-rt/include/arminc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcm20xx.h b/release/src-rt/include/bcm20xx.h deleted file mode 100644 index a372c2723b..0000000000 --- a/release/src-rt/include/bcm20xx.h +++ /dev/null @@ -1,1460 +0,0 @@ -/* - * Broadcom 20xx Digital Radios - * Chip-specific hardware definitions. - * - * Copyright (C) 2008, Broadcom Corporation - * All Rights Reserved. - * - * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; - * the contents of this file may not be disclosed to third parties, copied - * or duplicated in any form, in whole or in part, without the prior - * written permission of Broadcom Corporation. - * - * $Id: bcm20xx.h,v 13.44.2.1 2008/07/26 00:31:29 Exp $ - */ - -#ifndef _BCM20XX_H -#define _BCM20XX_H - -/* generic radio id ragister */ -#define RADIO_IDCODE 0x01 - -#define RADIO_DEFAULT_CORE 0 - -/* 2050 registers */ -#define RADIO_2050_READ_OFF 0x80 /* Read offset for all registers but idcode */ - -#define RADIO_2050_PLL_VAL 0x41 -#define RADIO_2050_PWR_CTL 0x43 -#define RADIO_2050_CAL_CTL 0x50 -#define RADIO_2050_TX_CTL0 0x51 -#define RADIO_2050_TX_CTL1 0x52 -#define RADIO_2050_PLL_OFFSET 0x58 -#define RADIO_2050_PLL_CTL0 0x5a -#define RADIO_2050_PLL_CTL1 0x5b -#define RADIO_2050_PLL_CTL2 0x5c -#define RADIO_2050_PLL_CTL3 0x5d -#define RADIO_2050_RX_LPF 0x60 -#define RADIO_2050_PU_OVR0 0x75 -#define RADIO_2050_PU_OVR 0x76 -#define RADIO_2050_RC_CAL_OVR 0x78 -#define RADIO_2050_RX_CTL0 0x7a - -/* New/changed registers in 2050sc: */ -#define RADIO_2050SC_TX_CTL2 0x53 -#define RADIO_2050SC_TX_CTL3 0x54 -#define RADIO_2050SC_PLL_CTL4 0x5e -#define RADIO_2050SC_RCAL_VAL0 0x60 -#define RADIO_2050SC_RCAL_VAL1 0x61 -#define RADIO_2050SC_RCAL_IND 0x62 -#define RADIO_2050SC_AGC_OVR 0x63 -#define RADIO_2050SC_FLTR_OVR 0x64 -#define RADIO_2050SC_CRY_TRIM0 0x73 -#define RADIO_2050SC_CRY_TRIM1 0x74 -#define RADIO_2050SC_RX_CTL1 0x7b -#define RADIO_2050SC_RX_CTL2 0x7c -#define RADIO_2050SC_RX_CTL3 0x7d -#define RADIO_2050SC_LNA_BIAS 0x7e -#define RADIO_2050SC_REF_SEL 0x7f - -/* Bits in RX_CTL0: */ -#define RXC0_RSSI_RST 0x80 -#define RXC0_MODE_RSSI 0x40 -#define RXC0_MODE_OFF 0x20 -#define RXC0_MODE_CM 0x10 -#define RXC0_LAN_LOAD 0x08 -#define RXC0_OFF_ADJ_MASK 0x07 - -/* Bits in TX_CTL0: */ -#define TXC0_MODE_TXLPF 0x04 -#define TXC0_PA_TSSI_EN 0x02 -#define TXC0_TSSI_EN 0x01 - -/* Bits in TX_CTL1: */ -#define TXC1_PA_GAIN_MASK 0x60 -#define TXC1_PA_GAIN_3DB 0x40 -#define TXC1_PA_GAIN_2DB 0x20 -#define TXC1_TX_MIX_GAIN 0x10 -#define TXC1_OFF_I_MASK 0x0c -#define TXC1_OFF_Q_MASK 0x03 - -/* 2055 registers */ -#define RADIO_2055_READ_OFF 0x100 /* Read offset for all registers but idcode */ - -#define RADIO_2055_GEN_SPARE 0x00 -#define RADIO_2055_SP_PIN_PD 0x02 -#define RADIO_2055_SP_RSSI_CORE1 0x03 -#define RADIO_2055_SP_PD_MISC_CORE1 0x04 -#define RADIO_2055_SP_RSSI_CORE2 0x05 -#define RADIO_2055_SP_PD_MISC_CORE2 0x06 -#define RADIO_2055_SP_RX_GC1_CORE1 0x07 -#define RADIO_2055_SP_RX_GC2_CORE1 0x08 -#define RADIO_2055_SP_RX_GC1_CORE2 0x09 -#define RADIO_2055_SP_RX_GC2_CORE2 0x0a -#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b -#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c -#define RADIO_2055_SP_TX_GC1_CORE1 0x0d -#define RADIO_2055_SP_TX_GC2_CORE1 0x0e -#define RADIO_2055_SP_TX_GC1_CORE2 0x0f -#define RADIO_2055_SP_TX_GC2_CORE2 0x10 -#define RADIO_2055_MASTER_CNTRL1 0x11 -#define RADIO_2055_MASTER_CNTRL2 0x12 -#define RADIO_2055_PD_LGEN 0x13 -#define RADIO_2055_PD_PLL_TS 0x14 -#define RADIO_2055_PD_CORE1_LGBUF 0x15 -#define RADIO_2055_PD_CORE1_TX 0x16 -#define RADIO_2055_PD_CORE1_RXTX 0x17 -#define RADIO_2055_PD_CORE1_RSSI_MISC 0x18 -#define RADIO_2055_PD_CORE2_LGBUF 0x19 -#define RADIO_2055_PD_CORE2_TX 0x1a -#define RADIO_2055_PD_CORE2_RXTX 0x1b -#define RADIO_2055_PD_CORE2_RSSI_MISC 0x1c -#define RADIO_2055_PWRDET_LGEN 0x1d -#define RADIO_2055_PWRDET_LGBUF_CORE1 0x1e -#define RADIO_2055_PWRDET_RXTX_CORE1 0x1f -#define RADIO_2055_PWRDET_LGBUF_CORE2 0x20 -#define RADIO_2055_PWRDET_RXTX_CORE2 0x21 -#define RADIO_2055_RRCCAL_CNTRL_SPARE 0x22 -#define RADIO_2055_RRCCAL_N_OPT_SEL 0x23 -#define RADIO_2055_CAL_MISC 0x24 -#define RADIO_2055_CAL_COUNTER_OUT 0x25 -#define RADIO_2055_CAL_COUNTER_OUT2 0x26 -#define RADIO_2055_CAL_CVAR_CNTRL 0x27 -#define RADIO_2055_CAL_RVAR_CNTRL 0x28 -#define RADIO_2055_CAL_LPO_CNTRL 0x29 -#define RADIO_2055_CAL_TS 0x2a -#define RADIO_2055_CAL_RCCAL_READ_TS 0x2b -#define RADIO_2055_CAL_RCAL_READ_TS 0x2c -#define RADIO_2055_PAD_DRIVER 0x2d -#define RADIO_2055_XO_CNTRL1 0x2e -#define RADIO_2055_XO_CNTRL2 0x2f -#define RADIO_2055_XO_REGULATOR 0x30 -#define RADIO_2055_XO_MISC 0x31 -#define RADIO_2055_PLL_LF_C1 0x32 -#define RADIO_2055_PLL_CAL_VTH 0x33 -#define RADIO_2055_PLL_LF_C2 0x34 -#define RADIO_2055_PLL_REF 0x35 -#define RADIO_2055_PLL_LF_R1 0x36 -#define RADIO_2055_PLL_PFD_CP 0x37 -#define RADIO_2055_PLL_IDAC_CPOPAMP 0x38 -#define RADIO_2055_PLL_CP_REGULATOR 0x39 -#define RADIO_2055_PLL_RCAL 0x3a -#define RADIO_2055_RF_PLL_MOD0 0x3b -#define RADIO_2055_RF_PLL_MOD1 0x3c -#define RADIO_2055_RF_MMD_IDAC1 0x3d -#define RADIO_2055_RF_MMD_IDAC0 0x3e -#define RADIO_2055_RF_MMD_SPARE 0x3f -#define RADIO_2055_VCO_CAL1 0x40 -#define RADIO_2055_VCO_CAL2 0x41 -#define RADIO_2055_VCO_CAL3 0x42 -#define RADIO_2055_VCO_CAL4 0x43 -#define RADIO_2055_VCO_CAL5 0x44 -#define RADIO_2055_VCO_CAL6 0x45 -#define RADIO_2055_VCO_CAL7 0x46 -#define RADIO_2055_VCO_CAL8 0x47 -#define RADIO_2055_VCO_CAL9 0x48 -#define RADIO_2055_VCO_CAL10 0x49 -#define RADIO_2055_VCO_CAL11 0x4a -#define RADIO_2055_VCO_CAL12 0x4b -#define RADIO_2055_VCO_CAL13 0x4c -#define RADIO_2055_VCO_CAL14 0x4d -#define RADIO_2055_VCO_CAL15 0x4e -#define RADIO_2055_VCO_CAL16 0x4f -#define RADIO_2055_VCO_KVCO 0x50 -#define RADIO_2055_VCO_CAP_TAIL 0x51 -#define RADIO_2055_VCO_IDAC_VCO 0x52 -#define RADIO_2055_VCO_REGULATOR 0x53 -#define RADIO_2055_PLL_RF_VTH 0x54 -#define RADIO_2055_LGBUF_CEN_BUF 0x55 -#define RADIO_2055_LGEN_TUNE1 0x56 -#define RADIO_2055_LGEN_TUNE2 0x57 -#define RADIO_2055_LGEN_IDAC1 0x58 -#define RADIO_2055_LGEN_IDAC2 0x59 -#define RADIO_2055_LGEN_BIAS_CNT 0x5a -#define RADIO_2055_LGEN_BIAS_IDAC 0x5b -#define RADIO_2055_LGEN_RCAL 0x5c -#define RADIO_2055_LGEN_DIV 0x5d -#define RADIO_2055_LGEN_SPARE2 0x5e -#define RADIO_2055_CORE1_LGBUF_A_TUNE 0x5f -#define RADIO_2055_CORE1_LGBUF_G_TUNE 0x60 -#define RADIO_2055_CORE1_LGBUF_DIV 0x61 -#define RADIO_2055_CORE1_LGBUF_A_IDAC 0x62 -#define RADIO_2055_CORE1_LGBUF_G_IDAC 0x63 -#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64 -#define RADIO_2055_CORE1_LGBUF_SPARE 0x65 -#define RADIO_2055_CORE1_RXRF_SPC1 0x66 -#define RADIO_2055_CORE1_RXRF_REG1 0x67 -#define RADIO_2055_CORE1_RXRF_REG2 0x68 -#define RADIO_2055_CORE1_RXRF_RCAL 0x69 -#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a -#define RADIO_2055_CORE1_RXBB_LPF 0x6b -#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c -#define RADIO_2055_CORE1_RXBB_VGA1_IDAC 0x6d -#define RADIO_2055_CORE1_RXBB_VGA2_IDAC 0x6e -#define RADIO_2055_CORE1_RXBB_VGA3_IDAC 0x6f -#define RADIO_2055_CORE1_RXBB_BUFO_CTRL 0x70 -#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71 -#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72 -#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73 -#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74 -#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75 -#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76 -#define RADIO_2055_CORE1_RXBB_REGULATOR 0x77 -#define RADIO_2055_CORE1_RXBB_SPARE1 0x78 -#define RADIO_2055_CORE1_RXTXBB_RCAL 0x79 -#define RADIO_2055_CORE1_TXRF_SGM_PGA 0x7a -#define RADIO_2055_CORE1_TXRF_SGM_PAD 0x7b -#define RADIO_2055_CORE1_TXRF_CNTR_PGA1 0x7c -#define RADIO_2055_CORE1_TXRF_CNTR_PAD1 0x7d -#define RADIO_2055_CORE1_TX_RFPGA_IDAC 0x7e -#define RADIO_2055_CORE1_TX_PGA_PAD_TN 0x7f -#define RADIO_2055_CORE1_TX_PAD_IDAC1 0x80 -#define RADIO_2055_CORE1_TX_PAD_IDAC2 0x81 -#define RADIO_2055_CORE1_TX_MX_BGTRIM 0x82 -#define RADIO_2055_CORE1_TXRF_RCAL 0x83 -#define RADIO_2055_CORE1_TXRF_PAD_TSSI1 0x84 -#define RADIO_2055_CORE1_TXRF_PAD_TSSI2 0x85 -#define RADIO_2055_CORE1_TX_RF_SPARE 0x86 -#define RADIO_2055_CORE1_TXRF_IQCAL1 0x87 -#define RADIO_2055_CORE1_TXRF_IQCAL2 0x88 -#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89 -#define RADIO_2055_CORE1_TXBB_LPF1 0x8a -#define RADIO_2055_CORE1_TX_VOS_CNCL 0x8b -#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c -#define RADIO_2055_CORE1_TX_BB_MXGM 0x8d -#define RADIO_2055_CORE2_LGBUF_A_TUNE 0x8e -#define RADIO_2055_CORE2_LGBUF_G_TUNE 0x8f -#define RADIO_2055_CORE2_LGBUF_DIV 0x90 -#define RADIO_2055_CORE2_LGBUF_A_IDAC 0x91 -#define RADIO_2055_CORE2_LGBUF_G_IDAC 0x92 -#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93 -#define RADIO_2055_CORE2_LGBUF_SPARE 0x94 -#define RADIO_2055_CORE2_RXRF_SPC1 0x95 -#define RADIO_2055_CORE2_RXRF_REG1 0x96 -#define RADIO_2055_CORE2_RXRF_REG2 0x97 -#define RADIO_2055_CORE2_RXRF_RCAL 0x98 -#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99 -#define RADIO_2055_CORE2_RXBB_LPF 0x9a -#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b -#define RADIO_2055_CORE2_RXBB_VGA1_IDAC 0x9c -#define RADIO_2055_CORE2_RXBB_VGA2_IDAC 0x9d -#define RADIO_2055_CORE2_RXBB_VGA3_IDAC 0x9e -#define RADIO_2055_CORE2_RXBB_BUFO_CTRL 0x9f -#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0 -#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1 -#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2 -#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3 -#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4 -#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5 -#define RADIO_2055_CORE2_RXBB_REGULATOR 0xa6 -#define RADIO_2055_CORE2_RXBB_SPARE1 0xa7 -#define RADIO_2055_CORE2_RXTXBB_RCAL 0xa8 -#define RADIO_2055_CORE2_TXRF_SGM_PGA 0xa9 -#define RADIO_2055_CORE2_TXRF_SGM_PAD 0xaa -#define RADIO_2055_CORE2_TXRF_CNTR_PGA1 0xab -#define RADIO_2055_CORE2_TXRF_CNTR_PAD1 0xac -#define RADIO_2055_CORE2_TX_RFPGA_IDAC 0xad -#define RADIO_2055_CORE2_TX_PGA_PAD_TN 0xae -#define RADIO_2055_CORE2_TX_PAD_IDAC1 0xaf -#define RADIO_2055_CORE2_TX_PAD_IDAC2 0xb0 -#define RADIO_2055_CORE2_TX_MX_BGTRIM 0xb1 -#define RADIO_2055_CORE2_TXRF_RCAL 0xb2 -#define RADIO_2055_CORE2_TXRF_PAD_TSSI1 0xb3 -#define RADIO_2055_CORE2_TXRF_PAD_TSSI2 0xb4 -#define RADIO_2055_CORE2_TX_RF_SPARE 0xb5 -#define RADIO_2055_CORE2_TXRF_IQCAL1 0xb6 -#define RADIO_2055_CORE2_TXRF_IQCAL2 0xb7 -#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8 -#define RADIO_2055_CORE2_TXBB_LPF1 0xb9 -#define RADIO_2055_CORE2_TX_VOS_CNCL 0xba -#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb -#define RADIO_2055_CORE2_TX_BB_MXGM 0xbc -#define RADIO_2055_PRG_GC_HPVGA23_21 0xbd -#define RADIO_2055_PRG_GC_HPVGA23_22 0xbe -#define RADIO_2055_PRG_GC_HPVGA23_23 0xbf -#define RADIO_2055_PRG_GC_HPVGA23_24 0xc0 -#define RADIO_2055_PRG_GC_HPVGA23_25 0xc1 -#define RADIO_2055_PRG_GC_HPVGA23_26 0xc2 -#define RADIO_2055_PRG_GC_HPVGA23_27 0xc3 -#define RADIO_2055_PRG_GC_HPVGA23_28 0xc4 -#define RADIO_2055_PRG_GC_HPVGA23_29 0xc5 -#define RADIO_2055_PRG_GC_HPVGA23_30 0xc6 -#define RADIO_2055_CORE1_LNA_GAINBST 0xcd -#define RADIO_2055_CORE1_B0_NBRSSI_VCM 0xd2 -#define RADIO_2055_CORE1_GEN_SPARE2 0xd6 -#define RADIO_2055_CORE2_LNA_GAINBST 0xd9 -#define RADIO_2055_CORE2_B0_NBRSSI_VCM 0xde -#define RADIO_2055_CORE2_GEN_SPARE2 0xe2 - -/* Gain expected from 2055 Gain boost */ -#define RADIO_2055_GAINBST_GAIN_DB 6 -#define RADIO_2055_GAINBST_CODE 0x6 - -/* 2055 bit masks */ -#define RADIO_2055_JTAGCTRL_MASK 0x04 -#define RADIO_2055_JTAGSYNC_MASK 0x08 -#define RADIO_2055_RRCAL_START 0x40 -#define RADIO_2055_RRCAL_RST_N 0x01 -#define RADIO_2055_CAL_LPO_ENABLE 0x80 -#define RADIO_2055_RCAL_DONE 0x80 -#define RADIO_2055_NBRSSI_VCM_I_MASK 0x03 -#define RADIO_2055_NBRSSI_VCM_I_SHIFT 0x00 -#define RADIO_2055_NBRSSI_VCM_Q_MASK 0x03 -#define RADIO_2055_NBRSSI_VCM_Q_SHIFT 0x00 -#define RADIO_2055_WBRSSI_VCM_IQ_MASK 0x0c -#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT 0x02 -#define RADIO_2055_NBRSSI_PD 0x01 -#define RADIO_2055_WBRSSI_G1_PD 0x04 -#define RADIO_2055_WBRSSI_G2_PD 0x02 -#define RADIO_2055_NBRSSI_SEL 0x01 -#define RADIO_2055_WBRSSI_G1_SEL 0x04 -#define RADIO_2055_WBRSSI_G2_SEL 0x02 -#define RADIO_2055_COUPLE_RX_MASK 0x01 -#define RADIO_2055_COUPLE_TX_MASK 0x02 -#define RADIO_2055_GAINBST_DISABLE 0x02 -#define RADIO_2055_GAINBST_VAL_MASK 0x07 -#define RADIO_2055_RXMX_GC_MASK 0x0c - - -/* 2055 pin control */ -#define RADIO_MIMO_CORESEL_OFF 0x0 -#define RADIO_MIMO_CORESEL_CORE1 0x1 -#define RADIO_MIMO_CORESEL_CORE2 0x2 -#define RADIO_MIMO_CORESEL_CORE3 0x3 -#define RADIO_MIMO_CORESEL_CORE4 0x4 -#define RADIO_MIMO_CORESEL_ALLRX 0x5 -#define RADIO_MIMO_CORESEL_ALLTX 0x6 -#define RADIO_MIMO_CORESEL_ALLRXTX 0x7 - - -/* 2060 registers */ -#define RADIO_2060WW_READ_OFF 0x40 /* Read offset for all registers but idcode */ - -/* 2060ww registers */ -#define RADIO_2060WW_RXGAINCTL 0x02 -#define RADIO_2060WW_PWR_DYNCTL 0x04 -#define RADIO_2060WW_PWR_STACTL 0x05 -#define RADIO_2060WW_RXLNA_DACC 0x06 -#define RADIO_2060WW_RX_VFC_LNA 0x07 -#define RADIO_2060WW_RX_MXCMVFC 0x08 -#define RADIO_2060WW_RX_GM_UPDN 0x09 -#define RADIO_2060WW_SGM_TEMPCO 0x0a -#define RADIO_2060WW_RXMIX_DACC 0x0b -#define RADIO_2060WW_RXVGA_DACC 0x0c -#define RADIO_2060WW_RX_AGC_CTL 0x0d -#define RADIO_2060WW_HPVGA1_TMR 0x0e -#define RADIO_2060WW_HPVGA2_TMR 0x0f -#define RADIO_2060WW_HPVGA3_TMR 0x10 -#define RADIO_2060WW_LPFMIX_TMR 0x11 -#define RADIO_2060WW_RXRSSI_DACC 0x12 -#define RADIO_2060WW_RX_SP_REG1 0x13 -#define RADIO_2060WW_RX_SP_REG2 0x14 -#define RADIO_2060WW_RX_SP_REG3 0x15 -#define RADIO_2060WW_RX_SP_REG4 0x16 -#define RADIO_2060WW_TX_BB_GAIN 0x17 -#define RADIO_2060WW_VC_TYPE_PA 0x18 -#define RADIO_2060WW_TX_RF_GAIN 0x19 -#define RADIO_2060WW_TX_MX_DACC 0x1a -#define RADIO_2060WW_TX_PA_DACC 0x1b -#define RADIO_2060WW_TX_BB_DACC 0x1c -#define RADIO_2060WW_TX_PV_DACC 0x1d -#define RADIO_2060WW_TX_VOS_CTL 0x1e -#define RADIO_2060WW_TX_CMV_ADJ 0x1f -#define RADIO_2060WW_TX_PAPADTN 0x20 -#define RADIO_2060WW_TX_LOMIXTN 0x21 -#define RADIO_2060WW_TX_RFPGATN 0x22 -#define RADIO_2060WW_TX_GMUPFN 0x23 -#define RADIO_2060WW_TX_PAPWRDT 0x24 -#define RADIO_2060WW_TX_SP_REG1 0x25 -#define RADIO_2060WW_TX_SP_REG2 0x26 -#define RADIO_2060WW_TX_SP_REG3 0x27 -#define RADIO_2060WW_TX_SP_REG4 0x28 -#define RADIO_2060WW_PLL_TMOUT 0x29 -#define RADIO_2060WW_VFC_VCOTAL 0x2a -#define RADIO_2060WW_VFC_LGNMIX 0x2b -#define RADIO_2060WW_PLL_GM_CTL 0x2c -#define RADIO_2060WW_PLL_REFDIV 0x2d -#define RADIO_2060WW_PLL_SD_CTL 0x2e -#define RADIO_2060WW_CCCP_PSCTL 0x2f -#define RADIO_2060WW_CCCP_OPALGN 0x30 -#define RADIO_2060WW_PLL_ADCVCO 0x31 -#define RADIO_2060WW_LOGEN_CUR1 0x32 -#define RADIO_2060WW_LOGEN_CUR2 0x33 -#define RADIO_2060WW_LOGEN_CUR3 0x34 -#define RADIO_2060WW_PLL_ERRTHR 0x35 -#define RADIO_2060WW_PLL_CALTHR 0x36 -#define RADIO_2060WW_CALIB_CODE 0x37 -#define RADIO_2060WW_PLL_CTLCODE 0x38 -#define RADIO_2060WW_LOGEN_SPARE 0x39 -#define RADIO_2060WW_PLL_CALOVR 0x3a -#define RADIO_2060WW_PLL_SP_REG1 0x3b -#define RADIO_2060WW_PLL_SP_REG2 0x3c -#define RADIO_2060WW_PLL_SP_REG3 0x3d -#define RADIO_2060WW_PLL_SP_REG4 0x3e -#define RADIO_2060WW_RC_CALVAL0 0x3f -#define RADIO_2060WW_RC_CALVAL1 0x80 -#define RADIO_2060WW_RST_PLLCAL 0x81 -#define RADIO_2060WW_CRY_CONTROL 0x82 -#define RADIO_2060WW_CRYST_BIAS 0x83 -#define RADIO_2060WW_RCAL_BGVAL 0x84 -#define RADIO_2060WW_RCALIB_OVR 0x85 - -/* 2062 registers */ -#define RADIO_2062_READ_OFF 0x100 /* Read offset for all registers but idcode */ - -/* Autogenerated by 2062_regs_tcl2c.tcl */ -#define RADIO_2062_COMMON_01_NORTH 0x0 -#define RADIO_2062_IDCODE_NORTH 0x1 -#define RADIO_2062_COMMON_02_NORTH 0x2 -#define RADIO_2062_COMMON_03_NORTH 0x3 -#define RADIO_2062_COMMON_04_NORTH 0x4 -#define RADIO_2062_COMMON_05_NORTH 0x5 -#define RADIO_2062_COMMON_06_NORTH 0x6 -#define RADIO_2062_COMMON_07_NORTH 0x7 -#define RADIO_2062_COMMON_08_NORTH 0x8 -#define RADIO_2062_COMMON_09_NORTH 0x9 -#define RADIO_2062_COMMON_10_NORTH 0xa -#define RADIO_2062_COMMON_11_NORTH 0xb -#define RADIO_2062_COMMON_12_NORTH 0xc -#define RADIO_2062_COMMON_13_NORTH 0xd -#define RADIO_2062_COMMON_14_NORTH 0xe -#define RADIO_2062_COMMON_15_NORTH 0xf -#define RADIO_2062_PDN_CTRL0_NORTH 0x10 -#define RADIO_2062_PDN_CTRL1_NORTH 0x11 -#define RADIO_2062_PDN_CTRL2_NORTH 0x12 -#define RADIO_2062_PDN_CTRL3_NORTH 0x13 -#define RADIO_2062_PDN_CTRL4_NORTH 0x14 -#define RADIO_2062_GEN_CTRL0_NORTH 0x15 -#define RADIO_2062_IQCAL_NORTH 0x16 -#define RADIO_2062_LGENC_NORTH 0x17 -#define RADIO_2062_LGENA_LPF_NORTH 0x18 -#define RADIO_2062_LGENA_BIAS0_NORTH 0x19 -#define RADIO_2062_LGNEA_BIAS1_NORTH 0x1a -#define RADIO_2062_LGENA_CTRL0_NORTH 0x1b -#define RADIO_2062_LGENA_CTRL1_NORTH 0x1c -#define RADIO_2062_LGENA_CTRL2_NORTH 0x1d -#define RADIO_2062_LGENA_TUNE0_NORTH 0x1e -#define RADIO_2062_LGENA_TUNE1_NORTH 0x1f -#define RADIO_2062_LGENA_TUNE2_NORTH 0x20 -#define RADIO_2062_LGENA_TUNE3_NORTH 0x21 -#define RADIO_2062_LGENA_CTRL3_NORTH 0x22 -#define RADIO_2062_LGENA_CTRL4_NORTH 0x23 -#define RADIO_2062_LGENA_CTRL5_NORTH 0x24 -#define RADIO_2062_LGENA_CTRL6_NORTH 0x25 -#define RADIO_2062_LGENA_CTRL7_NORTH 0x26 -#define RADIO_2062_RXA_CTRL0_NORTH 0x27 -#define RADIO_2062_RXA_CTRL1_NORTH 0x28 -#define RADIO_2062_RXA_CTRL2_NORTH 0x29 -#define RADIO_2062_RXA_CTRL3_NORTH 0x2a -#define RADIO_2062_RXA_CTRL4_NORTH 0x2b -#define RADIO_2062_RXA_CTRL5_NORTH 0x2c -#define RADIO_2062_RXA_CTRL6_NORTH 0x2d -#define RADIO_2062_RXA_CTRL7_NORTH 0x2e -#define RADIO_2062_RXBB_CTRL0_NORTH 0x2f -#define RADIO_2062_RXBB_CTRL1_NORTH 0x30 -#define RADIO_2062_RXBB_CTRL2_NORTH 0x31 -#define RADIO_2062_RXBB_GAIN0_NORTH 0x32 -#define RADIO_2062_RXBB_GAIN1_NORTH 0x33 -#define RADIO_2062_RXBB_GAIN2_NORTH 0x34 -#define RADIO_2062_RXBB_GAIN3_NORTH 0x35 -#define RADIO_2062_RXBB_RSSI0_NORTH 0x36 -#define RADIO_2062_RXBB_RSSI1_NORTH 0x37 -#define RADIO_2062_RXBB_CAL0_NORTH 0x38 -#define RADIO_2062_RXBB_CAL1_NORTH 0x39 -#define RADIO_2062_RXBB_CAL2_NORTH 0x3a -#define RADIO_2062_RXBB_BIAS0_NORTH 0x3b -#define RADIO_2062_RXBB_BIAS1_NORTH 0x3c -#define RADIO_2062_RXBB_BIAS2_NORTH 0x3d -#define RADIO_2062_RXBB_BIAS3_NORTH 0x3e -#define RADIO_2062_RXBB_BIAS4_NORTH 0x3f -#define RADIO_2062_RXBB_BIAS5_NORTH 0x40 -#define RADIO_2062_RXBB_RSSI2_NORTH 0x41 -#define RADIO_2062_RXBB_RSSI3_NORTH 0x42 -#define RADIO_2062_RXBB_RSSI4_NORTH 0x43 -#define RADIO_2062_RXBB_RSSI5_NORTH 0x44 -#define RADIO_2062_TX_CTRL0_NORTH 0x45 -#define RADIO_2062_TX_CTRL1_NORTH 0x46 -#define RADIO_2062_TX_CTRL2_NORTH 0x47 -#define RADIO_2062_TX_CTRL3_NORTH 0x48 -#define RADIO_2062_TX_CTRL4_NORTH 0x49 -#define RADIO_2062_TX_CTRL5_NORTH 0x4a -#define RADIO_2062_TX_CTRL6_NORTH 0x4b -#define RADIO_2062_TX_CTRL7_NORTH 0x4c -#define RADIO_2062_TX_CTRL8_NORTH 0x4d -#define RADIO_2062_TX_CTRL9_NORTH 0x4e -#define RADIO_2062_TX_CTRLA_NORTH 0x4f -#define RADIO_2062_TX_GC2G_NORTH 0x50 -#define RADIO_2062_TX_GC5G_NORTH 0x51 -#define RADIO_2062_TX_TUNE_NORTH 0x52 -#define RADIO_2062_TX_PAD_NORTH 0x53 -#define RADIO_2062_TX_PGA_NORTH 0x54 -#define RADIO_2062_TX_PADAUX_NORTH 0x55 -#define RADIO_2062_TX_PGAAUX_NORTH 0x56 -#define RADIO_2062_TSSI_CTRL0_NORTH 0x57 -#define RADIO_2062_TSSI_CTRL1_NORTH 0x58 -#define RADIO_2062_TSSI_CTRL2_NORTH 0x59 -#define RADIO_2062_IQCAL_CTRL0_NORTH 0x5a -#define RADIO_2062_IQCAL_CTRL1_NORTH 0x5b -#define RADIO_2062_IQCAL_CTRL2_NORTH 0x5c -#define RADIO_2062_CAL_TS_NORTH 0x5d -#define RADIO_2062_CAL_CTRL0_NORTH 0x5e -#define RADIO_2062_CAL_CTRL1_NORTH 0x5f -#define RADIO_2062_CAL_CTRL2_NORTH 0x60 -#define RADIO_2062_CAL_CTRL3_NORTH 0x61 -#define RADIO_2062_CAL_CTRL4_NORTH 0x62 -#define RADIO_2062_CAL_DBG0_NORTH 0x63 -#define RADIO_2062_CAL_DBG1_NORTH 0x64 -#define RADIO_2062_CAL_DBG2_NORTH 0x65 -#define RADIO_2062_CAL_DBG3_NORTH 0x66 -#define RADIO_2062_PSENSE_CTRL0_NORTH 0x69 -#define RADIO_2062_PSENSE_CTRL1_NORTH 0x6a -#define RADIO_2062_PSENSE_CTRL2_NORTH 0x6b -#define RADIO_2062_TEST_BUF0_NORTH 0x6c -#define RADIO_2062_COMMON_01_SOUTH 0x4000 -#define RADIO_2062_IDCODE_SOUTH 0x4001 -#define RADIO_2062_COMMON_02_SOUTH 0x4002 -#define RADIO_2062_COMMON_03_SOUTH 0x4003 -#define RADIO_2062_COMMON_04_SOUTH 0x4004 -#define RADIO_2062_COMMON_05_SOUTH 0x4005 -#define RADIO_2062_COMMON_06_SOUTH 0x4006 -#define RADIO_2062_COMMON_07_SOUTH 0x4007 -#define RADIO_2062_COMMON_08_SOUTH 0x4008 -#define RADIO_2062_COMMON_09_SOUTH 0x4009 -#define RADIO_2062_COMMON_10_SOUTH 0x400a -#define RADIO_2062_COMMON_11_SOUTH 0x400b -#define RADIO_2062_COMMON_12_SOUTH 0x400c -#define RADIO_2062_COMMON_13_SOUTH 0x400d -#define RADIO_2062_COMMON_14_SOUTH 0x400e -#define RADIO_2062_COMMON_15_SOUTH 0x400f -#define RADIO_2062_PDS_CTRL0_SOUTH 0x4010 -#define RADIO_2062_PDS_CTRL1_SOUTH 0x4011 -#define RADIO_2062_PDS_CTRL2_SOUTH 0x4012 -#define RADIO_2062_PDS_CTRL3_SOUTH 0x4013 -#define RADIO_2062_BG_CTRL0_SOUTH 0x4014 -#define RADIO_2062_BG_CTRL1_SOUTH 0x4015 -#define RADIO_2062_BG_CTRL2_SOUTH 0x4016 -#define RADIO_2062_LGENG_CTRL00_SOUTH 0x4017 -#define RADIO_2062_LGENG_CTRL01_SOUTH 0x4018 -#define RADIO_2062_LGENG_CTRL02_SOUTH 0x4019 -#define RADIO_2062_LGENG_CTRL03_SOUTH 0x401a -#define RADIO_2062_LGENG_CTRL04_SOUTH 0x401b -#define RADIO_2062_LGENG_CTRL05_SOUTH 0x401c -#define RADIO_2062_LGENG_CTRL06_SOUTH 0x401d -#define RADIO_2062_LGENG_CTRL07_SOUTH 0x401e -#define RADIO_2062_LGENG_CTRL08_SOUTH 0x401f -#define RADIO_2062_LGENG_CTRL09_SOUTH 0x4020 -#define RADIO_2062_LGENG_CTRL10_SOUTH 0x4021 -#define RADIO_2062_LGENG_CTRL11_SOUTH 0x4022 -#define RADIO_2062_REFPLL_CTRL00_SOUTH 0x4023 -#define RADIO_2062_REFPLL_CTRL01_SOUTH 0x4024 -#define RADIO_2062_REFPLL_CTRL02_SOUTH 0x4025 -#define RADIO_2062_REFPLL_CTRL03_SOUTH 0x4026 -#define RADIO_2062_REFPLL_CTRL04_SOUTH 0x4027 -#define RADIO_2062_REFPLL_CTRL05_SOUTH 0x4028 -#define RADIO_2062_REFPLL_CTRL06_SOUTH 0x4029 -#define RADIO_2062_REFPLL_CTRL07_SOUTH 0x402a -#define RADIO_2062_REFPLL_CTRL08_SOUTH 0x402b -#define RADIO_2062_REFPLL_CTRL09_SOUTH 0x402c -#define RADIO_2062_REFPLL_CTRL10_SOUTH 0x402d -#define RADIO_2062_REFPLL_CTRL11_SOUTH 0x402e -#define RADIO_2062_REFPLL_CTRL12_SOUTH 0x402f -#define RADIO_2062_REFPLL_CTRL13_SOUTH 0x4030 -#define RADIO_2062_REFPLL_CTRL14_SOUTH 0x4031 -#define RADIO_2062_REFPLL_CTRL15_SOUTH 0x4032 -#define RADIO_2062_REFPLL_CTRL16_SOUTH 0x4033 -#define RADIO_2062_RFPLL_CTRL00_SOUTH 0x4034 -#define RADIO_2062_RFPLL_CTRL01_SOUTH 0x4035 -#define RADIO_2062_RFPLL_CTRL02_SOUTH 0x4036 -#define RADIO_2062_RFPLL_CTRL03_SOUTH 0x4037 -#define RADIO_2062_RFPLL_CTRL04_SOUTH 0x4038 -#define RADIO_2062_RFPLL_CTRL05_SOUTH 0x4039 -#define RADIO_2062_RFPLL_CTRL06_SOUTH 0x403a -#define RADIO_2062_RFPLL_CTRL07_SOUTH 0x403b -#define RADIO_2062_RFPLL_CTRL08_SOUTH 0x403c -#define RADIO_2062_RFPLL_CTRL09_SOUTH 0x403d -#define RADIO_2062_RFPLL_CTRL10_SOUTH 0x403e -#define RADIO_2062_RFPLL_CTRL11_SOUTH 0x403f -#define RADIO_2062_RFPLL_CTRL12_SOUTH 0x4040 -#define RADIO_2062_RFPLL_CTRL13_SOUTH 0x4041 -#define RADIO_2062_RFPLL_CTRL14_SOUTH 0x4042 -#define RADIO_2062_RFPLL_CTRL15_SOUTH 0x4043 -#define RADIO_2062_RFPLL_CTRL16_SOUTH 0x4044 -#define RADIO_2062_RFPLL_CTRL17_SOUTH 0x4045 -#define RADIO_2062_RFPLL_CTRL18_SOUTH 0x4046 -#define RADIO_2062_RFPLL_CTRL19_SOUTH 0x4047 -#define RADIO_2062_RFPLL_CTRL20_SOUTH 0x4048 -#define RADIO_2062_RFPLL_CTRL21_SOUTH 0x4049 -#define RADIO_2062_RFPLL_CTRL22_SOUTH 0x404a -#define RADIO_2062_RFPLL_CTRL23_SOUTH 0x404b -#define RADIO_2062_RFPLL_CTRL24_SOUTH 0x404c -#define RADIO_2062_RFPLL_CTRL25_SOUTH 0x404d -#define RADIO_2062_RFPLL_CTRL26_SOUTH 0x404e -#define RADIO_2062_RFPLL_CTRL27_SOUTH 0x404f -#define RADIO_2062_RFPLL_CTRL28_SOUTH 0x4050 -#define RADIO_2062_RFPLL_CTRL29_SOUTH 0x4051 -#define RADIO_2062_RFPLL_CTRL30_SOUTH 0x4052 -#define RADIO_2062_RFPLL_CTRL31_SOUTH 0x4053 -#define RADIO_2062_RFPLL_CTRL32_SOUTH 0x4054 -#define RADIO_2062_RFPLL_CTRL33_SOUTH 0x4055 -#define RADIO_2062_RFPLL_CTRL34_SOUTH 0x4056 -#define RADIO_2062_RXG_CTR00_SOUTH 0x4057 -#define RADIO_2062_RXG_CTR01_SOUTH 0x4058 -#define RADIO_2062_RXG_CTR02_SOUTH 0x4059 -#define RADIO_2062_RXG_CTR03_SOUTH 0x405a -#define RADIO_2062_RXG_CTR04_SOUTH 0x405b -#define RADIO_2062_RXG_CTR05_SOUTH 0x405c -#define RADIO_2062_RXG_CTR06_SOUTH 0x405d -#define RADIO_2062_RXG_CTR07_SOUTH 0x405e -#define RADIO_2062_RXG_CTR08_SOUTH 0x405f -#define RADIO_2062_RXG_CTR09_SOUTH 0x4060 -#define RADIO_2062_RXG_CTR10_SOUTH 0x4061 -#define RADIO_2062_RXG_CTR11_SOUTH 0x4062 -#define RADIO_2062_RXG_CTR12_SOUTH 0x4063 -#define RADIO_2062_RXG_CTR13_SOUTH 0x4064 -#define RADIO_2062_RXG_CTR14_SOUTH 0x4065 -#define RADIO_2062_RXG_CTR15_SOUTH 0x4066 -#define RADIO_2062_RXG_CTR16_SOUTH 0x4067 -#define RADIO_2062_RXG_CTR17_SOUTH 0x4068 -#define RADIO_2063_COMMON_01 0x0 - -/* 2063 registers */ -#define RADIO_2063_READ_OFF 0x200 /* Read offset for all registers but idcode */ - -/* Autogenerated by 2063_regs_tcl2c.tcl */ -#define RADIO_2063_COMMON_01 0x0 -#define RADIO_2063_IDCODE 0x1 -#define RADIO_2063_COMMON_02 0x2 -#define RADIO_2063_COMMON_03 0x3 -#define RADIO_2063_COMMON_04 0x4 -#define RADIO_2063_COMMON_05 0x5 -#define RADIO_2063_COMMON_06 0x6 -#define RADIO_2063_COMMON_07 0x7 -#define RADIO_2063_COMMON_08 0x8 -#define RADIO_2063_COMMON_09 0x9 -#define RADIO_2063_COMMON_10 0xa -#define RADIO_2063_COMMON_11 0xb -#define RADIO_2063_COMMON_12 0xc -#define RADIO_2063_COMMON_13 0xd -#define RADIO_2063_COMMON_14 0xe -#define RADIO_2063_COMMON_15 0xf -#define RADIO_2063_COMMON_16 0x10 -#define RADIO_2063_COMMON_17 0x11 -#define RADIO_2063_COMMON_18 0x12 -#define RADIO_2063_COMMON_19 0x13 -#define RADIO_2063_COMMON_20 0x14 -#define RADIO_2063_COMMON_21 0x15 -#define RADIO_2063_COMMON_22 0x16 -#define RADIO_2063_COMMON_23 0x17 -#define RADIO_2063_COMMON_24 0x18 -#define RADIO_2063_POWER_SWITCH_CTRL 0x19 -#define RADIO_2063_PLL_SP_1 0x1a -#define RADIO_2063_PLL_SP_2 0x1b -#define RADIO_2063_LOGEN_SP_1 0x1c -#define RADIO_2063_LOGEN_SP_2 0x1d -#define RADIO_2063_LOGEN_SP_3 0x1e -#define RADIO_2063_LOGEN_SP_4 0x1f -#define RADIO_2063_LOGEN_SP_5 0x20 -#define RADIO_2063_GRX_SP_1 0x21 -#define RADIO_2063_GRX_SP_2 0x22 -#define RADIO_2063_GRX_SP_3 0x23 -#define RADIO_2063_GRX_SP_4 0x24 -#define RADIO_2063_GRX_SP_5 0x25 -#define RADIO_2063_GRX_SP_6 0x26 -#define RADIO_2063_GRX_SP_7 0x27 -#define RADIO_2063_GRX_SP_8 0x28 -#define RADIO_2063_GRX_SP_9 0x29 -#define RADIO_2063_GRX_SP_10 0x2a -#define RADIO_2063_GRX_SP_11 0x2b -#define RADIO_2063_ARX_SP_1 0x2c -#define RADIO_2063_ARX_SP_2 0x2d -#define RADIO_2063_ARX_SP_3 0x2e -#define RADIO_2063_ARX_SP_4 0x2f -#define RADIO_2063_ARX_SP_5 0x30 -#define RADIO_2063_ARX_SP_6 0x31 -#define RADIO_2063_ARX_SP_7 0x32 -#define RADIO_2063_RXBB_SP_1 0x33 -#define RADIO_2063_RXBB_SP_2 0x34 -#define RADIO_2063_RXBB_SP_3 0x35 -#define RADIO_2063_RXBB_SP_4 0x36 -#define RADIO_2063_RXBB_SP_5 0x37 -#define RADIO_2063_RXBB_SP_6 0x38 -#define RADIO_2063_RXBB_SP_7 0x39 -#define RADIO_2063_RXBB_SP_8 0x3a -#define RADIO_2063_TXRF_SP_1 0x3b -#define RADIO_2063_TXRF_SP_2 0x3c -#define RADIO_2063_TXRF_SP_3 0x3d -#define RADIO_2063_TXRF_SP_4 0x3e -#define RADIO_2063_TXRF_SP_5 0x3f -#define RADIO_2063_TXRF_SP_6 0x40 -#define RADIO_2063_TXRF_SP_7 0x41 -#define RADIO_2063_TXRF_SP_8 0x42 -#define RADIO_2063_TXRF_SP_9 0x43 -#define RADIO_2063_TXRF_SP_10 0x44 -#define RADIO_2063_TXRF_SP_11 0x45 -#define RADIO_2063_TXRF_SP_12 0x46 -#define RADIO_2063_TXRF_SP_13 0x47 -#define RADIO_2063_TXRF_SP_14 0x48 -#define RADIO_2063_TXRF_SP_15 0x49 -#define RADIO_2063_TXRF_SP_16 0x4a -#define RADIO_2063_TXRF_SP_17 0x4b -#define RADIO_2063_PA_SP_1 0x4c -#define RADIO_2063_PA_SP_2 0x4d -#define RADIO_2063_PA_SP_3 0x4e -#define RADIO_2063_PA_SP_4 0x4f -#define RADIO_2063_PA_SP_5 0x50 -#define RADIO_2063_PA_SP_6 0x51 -#define RADIO_2063_PA_SP_7 0x52 -#define RADIO_2063_TXBB_SP_1 0x53 -#define RADIO_2063_TXBB_SP_2 0x54 -#define RADIO_2063_TXBB_SP_3 0x55 -#define RADIO_2063_REG_SP_1 0x56 -#define RADIO_2063_BANDGAP_CTRL_1 0x57 -#define RADIO_2063_BANDGAP_CTRL_2 0x58 -#define RADIO_2063_LPO_CTRL_1 0x59 -#define RADIO_2063_RCCAL_CTRL_1 0x5a -#define RADIO_2063_RCCAL_CTRL_2 0x5b -#define RADIO_2063_RCCAL_CTRL_3 0x5c -#define RADIO_2063_RCCAL_CTRL_4 0x5d -#define RADIO_2063_RCCAL_CTRL_5 0x5e -#define RADIO_2063_RCCAL_CTRL_6 0x5f -#define RADIO_2063_RCCAL_CTRL_7 0x60 -#define RADIO_2063_RCCAL_CTRL_8 0x61 -#define RADIO_2063_RCCAL_CTRL_9 0x62 -#define RADIO_2063_RCCAL_CTRL_10 0x63 -#define RADIO_2063_PLL_JTAG_CALNRST 0x64 -#define RADIO_2063_PLL_JTAGIN_PLL_1 0x65 -#define RADIO_2063_PLL_JTAGIN_PLL_2 0x66 -#define RADIO_2063_PLL_JTAG_PLL_CP_1 0x67 -#define RADIO_2063_PLL_JTAG_PLL_CP_2 0x68 -#define RADIO_2063_PLL_JTAG_PLL_CP_3 0x69 -#define RADIO_2063_PLL_JTAG_PLL_CP_4 0x6a -#define RADIO_2063_PLL_JTAG_PLL_CTL_1 0x6b -#define RADIO_2063_PLL_JTAG_PLL_LF_1 0x6c -#define RADIO_2063_PLL_JTAG_PLL_LF_2 0x6d -#define RADIO_2063_PLL_JTAG_PLL_LF_3 0x6e -#define RADIO_2063_PLL_JTAG_PLL_LF_4 0x6f -#define RADIO_2063_PLL_JTAG_PLL_SG_1 0x70 -#define RADIO_2063_PLL_JTAG_PLL_SG_2 0x71 -#define RADIO_2063_PLL_JTAG_PLL_SG_3 0x72 -#define RADIO_2063_PLL_JTAG_PLL_SG_4 0x73 -#define RADIO_2063_PLL_JTAG_PLL_SG_5 0x74 -#define RADIO_2063_PLL_JTAG_PLL_VCO_1 0x75 -#define RADIO_2063_PLL_JTAG_PLL_VCO_2 0x76 -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_1 0x77 -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_2 0x78 -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_3 0x79 -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_4 0x7a -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_5 0x7b -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_6 0x7c -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_7 0x7d -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_8 0x7e -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_9 0x7f -#define RADIO_2063_PLL_JTAG_PLL_VCOCAL_10 0x80 -#define RADIO_2063_PLL_JTAG_PLL_XTAL_1_2 0x81 -#define RADIO_2063_PLL_JTAG_PLL_XTAL_3 0x82 -#define RADIO_2063_LOGEN_ACL_1 0x83 -#define RADIO_2063_LOGEN_ACL_2 0x84 -#define RADIO_2063_LOGEN_ACL_3 0x85 -#define RADIO_2063_LOGEN_ACL_4 0x86 -#define RADIO_2063_LOGEN_ACL_5 0x87 -#define RADIO_2063_LOCAL_INPUTS 0x88 -#define RADIO_2063_LOCAL_CTRL_1 0x89 -#define RADIO_2063_LOCAL_CTRL_2 0x8a -#define RADIO_2063_LOCAL_CTRL_3 0x8b -#define RADIO_2063_LOCAL_WAITCNT 0x8c -#define RADIO_2063_LOCAL_OVR_1 0x8d -#define RADIO_2063_LOCAL_OVR_2 0x8e -#define RADIO_2063_LOCAL_OVAL_1 0x8f -#define RADIO_2063_LOCAL_OVAL_2 0x90 -#define RADIO_2063_LOCAL_OVAL_3 0x91 -#define RADIO_2063_LOCAL_OVAL_4 0x92 -#define RADIO_2063_LOCAL_OVAL_5 0x93 -#define RADIO_2063_LOCAL_OVAL_6 0x94 -#define RADIO_2063_LOCAL_OVAL_7 0x95 -#define RADIO_2063_LOCAL_CALVLD_1 0x96 -#define RADIO_2063_LOCAL_CALVLD_2 0x97 -#define RADIO_2063_LOCAL_CVAL_1 0x98 -#define RADIO_2063_LOCAL_CVAL_2 0x99 -#define RADIO_2063_LOCAL_CVAL_3 0x9a -#define RADIO_2063_LOCAL_CVAL_4 0x9b -#define RADIO_2063_LOCAL_CVAL_5 0x9c -#define RADIO_2063_LOCAL_CVAL_6 0x9d -#define RADIO_2063_LOCAL_CVAL_7 0x9e -#define RADIO_2063_LOGEN_CAL_EN 0x9f -#define RADIO_2063_LOGEN_PEAKDET_1 0xa0 -#define RADIO_2063_LOGEN_RCCR_1 0xa1 -#define RADIO_2063_LOGEN_VCOBUF_1 0xa2 -#define RADIO_2063_LOGEN_MIXER_1 0xa3 -#define RADIO_2063_LOGEN_MIXER_2 0xa4 -#define RADIO_2063_LOGEN_BUF_1 0xa5 -#define RADIO_2063_LOGEN_BUF_2 0xa6 -#define RADIO_2063_LOGEN_DIV_1 0xa7 -#define RADIO_2063_LOGEN_DIV_2 0xa8 -#define RADIO_2063_LOGEN_DIV_3 0xa9 -#define RADIO_2063_LOGEN_CBUFRX_1 0xaa -#define RADIO_2063_LOGEN_CBUFRX_2 0xab -#define RADIO_2063_LOGEN_CBUFTX_1 0xac -#define RADIO_2063_LOGEN_CBUFTX_2 0xad -#define RADIO_2063_LOGEN_IDAC_1 0xae -#define RADIO_2063_LOGEN_SPARE_1 0xaf -#define RADIO_2063_LOGEN_SPARE_2 0xb0 -#define RADIO_2063_LOGEN_SPARE_3 0xb1 -#define RADIO_2063_GRX_1ST_1 0xb2 -#define RADIO_2063_GRX_1ST_2 0xb3 -#define RADIO_2063_GRX_1ST_3 0xb4 -#define RADIO_2063_GRX_2ND_1 0xb5 -#define RADIO_2063_GRX_2ND_2 0xb6 -#define RADIO_2063_GRX_2ND_3 0xb7 -#define RADIO_2063_GRX_2ND_4 0xb8 -#define RADIO_2063_GRX_2ND_5 0xb9 -#define RADIO_2063_GRX_2ND_6 0xba -#define RADIO_2063_GRX_2ND_7 0xbb -#define RADIO_2063_GRX_2ND_8 0xbc -#define RADIO_2063_GRX_PS_1 0xbd -#define RADIO_2063_GRX_PS_2 0xbe -#define RADIO_2063_GRX_PS_3 0xbf -#define RADIO_2063_GRX_PS_4 0xc0 -#define RADIO_2063_GRX_PS_5 0xc1 -#define RADIO_2063_GRX_MIX_1 0xc2 -#define RADIO_2063_GRX_MIX_2 0xc3 -#define RADIO_2063_GRX_MIX_3 0xc4 -#define RADIO_2063_GRX_MIX_4 0xc5 -#define RADIO_2063_GRX_MIX_5 0xc6 -#define RADIO_2063_GRX_MIX_6 0xc7 -#define RADIO_2063_GRX_MIX_7 0xc8 -#define RADIO_2063_GRX_MIX_8 0xc9 -#define RADIO_2063_GRX_PDET_1 0xca -#define RADIO_2063_GRX_SPARES_1 0xcb -#define RADIO_2063_GRX_SPARES_2 0xcc -#define RADIO_2063_GRX_SPARES_3 0xcd -#define RADIO_2063_ARX_1ST_1 0xce -#define RADIO_2063_ARX_1ST_2 0xcf -#define RADIO_2063_ARX_1ST_3 0xd0 -#define RADIO_2063_ARX_1ST_4 0xd1 -#define RADIO_2063_ARX_1ST_5 0xd2 -#define RADIO_2063_ARX_2ND_1 0xd3 -#define RADIO_2063_ARX_2ND_2 0xd4 -#define RADIO_2063_ARX_2ND_3 0xd5 -#define RADIO_2063_ARX_2ND_4 0xd6 -#define RADIO_2063_ARX_2ND_5 0xd7 -#define RADIO_2063_ARX_2ND_6 0xd8 -#define RADIO_2063_ARX_2ND_7 0xd9 -#define RADIO_2063_ARX_PS_1 0xda -#define RADIO_2063_ARX_PS_2 0xdb -#define RADIO_2063_ARX_PS_3 0xdc -#define RADIO_2063_ARX_PS_4 0xdd -#define RADIO_2063_ARX_PS_5 0xde -#define RADIO_2063_ARX_PS_6 0xdf -#define RADIO_2063_ARX_MIX_1 0xe0 -#define RADIO_2063_ARX_MIX_2 0xe1 -#define RADIO_2063_ARX_MIX_3 0xe2 -#define RADIO_2063_ARX_MIX_4 0xe3 -#define RADIO_2063_ARX_MIX_5 0xe4 -#define RADIO_2063_ARX_MIX_6 0xe5 -#define RADIO_2063_ARX_MIX_7 0xe6 -#define RADIO_2063_ARX_MIX_8 0xe7 -#define RADIO_2063_ARX_PWRDET_1 0xe8 -#define RADIO_2063_ARX_SPARE_1 0xe9 -#define RADIO_2063_ARX_SPARE_2 0xea -#define RADIO_2063_ARX_SPARE_3 0xeb -#define RADIO_2063_RXTIA_CTRL_1 0xec -#define RADIO_2063_RXTIA_CTRL_2 0xed -#define RADIO_2063_RXTIA_CTRL_3 0xee -#define RADIO_2063_RXTIA_CTRL_4 0xef -#define RADIO_2063_RXTIA_CTRL_5 0xf0 -#define RADIO_2063_RXTIA_CTRL_6 0xf1 -#define RADIO_2063_RXBB_CTRL_1 0xf2 -#define RADIO_2063_RXBB_CTRL_2 0xf3 -#define RADIO_2063_RXBB_CTRL_3 0xf4 -#define RADIO_2063_RXBB_CTRL_4 0xf5 -#define RADIO_2063_RXBB_CTRL_5 0xf6 -#define RADIO_2063_RXBB_CTRL_6 0xf7 -#define RADIO_2063_RXBB_CTRL_7 0xf8 -#define RADIO_2063_RXBB_CTRL_8 0xf9 -#define RADIO_2063_RXBB_CTRL_9 0xfa -#define RADIO_2063_TXRF_CTRL_1 0xfb -#define RADIO_2063_TXRF_IDAC_LO_RF_I 0xfc -#define RADIO_2063_TXRF_IDAC_LO_RF_Q 0xfd -#define RADIO_2063_TXRF_IDAC_LO_BB_I 0xfe -#define RADIO_2063_TXRF_IDAC_LO_BB_Q 0xff -#define RADIO_2063_TXRF_CTRL_2 0x100 -#define RADIO_2063_TXRF_CTRL_3 0x101 -#define RADIO_2063_TXRF_CTRL_4 0x102 -#define RADIO_2063_TXRF_CTRL_5 0x103 -#define RADIO_2063_TXRF_CTRL_6 0x104 -#define RADIO_2063_TXRF_CTRL_7 0x105 -#define RADIO_2063_TXRF_CTRL_8 0x106 -#define RADIO_2063_TXRF_CTRL_9 0x107 -#define RADIO_2063_TXRF_CTRL_10 0x108 -#define RADIO_2063_TXRF_CTRL_14 0x109 -#define RADIO_2063_TXRF_CTRL_15 0x10a -#define RADIO_2063_PA_CTRL_1 0x10b -#define RADIO_2063_PA_CTRL_2 0x10c -#define RADIO_2063_PA_CTRL_3 0x10d -#define RADIO_2063_PA_CTRL_4 0x10e -#define RADIO_2063_PA_CTRL_5 0x10f -#define RADIO_2063_PA_CTRL_6 0x110 -#define RADIO_2063_PA_CTRL_7 0x111 -#define RADIO_2063_PA_CTRL_8 0x112 -#define RADIO_2063_PA_CTRL_9 0x113 -#define RADIO_2063_PA_CTRL_10 0x114 -#define RADIO_2063_PA_CTRL_11 0x115 -#define RADIO_2063_PA_CTRL_12 0x116 -#define RADIO_2063_PA_CTRL_13 0x117 -#define RADIO_2063_TXBB_CTRL_1 0x118 -#define RADIO_2063_TXBB_CTRL_2 0x119 -#define RADIO_2063_TXBB_CTRL_3 0x11a -#define RADIO_2063_TXBB_CTRL_4 0x11b -#define RADIO_2063_GPIO_CTRL_1 0x11c -#define RADIO_2063_VREG_CTRL_1 0x11d -#define RADIO_2063_AMUX_CTRL_1 0x11e -#define RADIO_2063_IQCAL_GVAR 0x11f -#define RADIO_2063_IQCAL_CTRL_1 0x120 -#define RADIO_2063_IQCAL_CTRL_2 0x121 -#define RADIO_2063_TEMPSENSE_CTRL_1 0x122 -#define RADIO_2063_TEMPSENSE_CTRL_2 0x123 -#define RADIO_2063_TXRX_LOOPBACK_1 0x124 -#define RADIO_2063_TXRX_LOOPBACK_2 0x125 -#define RADIO_2063_EXTTSSI_CTRL_1 0x126 -#define RADIO_2063_EXTTSSI_CTRL_2 0x127 -#define RADIO_2063_AFE_CTRL 0x128 -#define RADIO_2063_TXBB_CTRL_6 0x129 -#define RADIO_2063_TXBB_CTRL_7 0x12a -#define RADIO_2063_TXBB_CTRL_8 0x12b -#define RADIO_2063_TXBB_CTRL_9 0x12c -#define RADIO_2063_TXBB_CTRL_10 0x12d -#define RADIO_2063_TXBB_CTRL_11 0x12e -#define RADIO_2063_TXBB_CTRL_12 0x12f -#define RADIO_2063_TXBB_CTRL_13 0x130 -#define RADIO_2063_TXBB_CTRL_14 0x131 -#define RADIO_2063_TXBB_CTRL_15 0x132 -#define RADIO_2063_TXBB_CTRL_16 0x133 -#define RADIO_2063_TXBB_CTRL_17 0x134 -#define RADIO_2063_TXBB_CTRL_18 0x135 -#define RADIO_2063_TXBB_CTRL_19 0x136 -#define RADIO_2063_AFE_LOOPBACK_CTRL_1 0x137 -#define RADIO_2063_PA_CTRL_14 0x138 -#define RADIO_2063_PA_CTRL_15 0x139 - -/* Auto-generated 2056 register definitions */ -#define RADIO_2056_SYN (0x0 << 12) -#define RADIO_2056_TX0 (0x2 << 12) -#define RADIO_2056_TX1 (0x3 << 12) -#define RADIO_2056_RX0 (0x6 << 12) -#define RADIO_2056_RX1 (0x7 << 12) -#define RADIO_2056_ALLTX (0xe << 12) -#define RADIO_2056_ALLRX (0xf << 12) - -#define RADIO_2056_SYN_RESERVED_ADDR0 0x0 -#define RADIO_2056_SYN_IDCODE 0x1 -#define RADIO_2056_SYN_RESERVED_ADDR2 0x2 -#define RADIO_2056_SYN_RESERVED_ADDR3 0x3 -#define RADIO_2056_SYN_RESERVED_ADDR4 0x4 -#define RADIO_2056_SYN_RESERVED_ADDR5 0x5 -#define RADIO_2056_SYN_RESERVED_ADDR6 0x6 -#define RADIO_2056_SYN_RESERVED_ADDR7 0x7 -#define RADIO_2056_SYN_COM_CTRL 0x8 -#define RADIO_2056_SYN_COM_PU 0x9 -#define RADIO_2056_SYN_COM_OVR 0xa -#define RADIO_2056_SYN_COM_RESET 0xb -#define RADIO_2056_SYN_COM_RCAL 0xc -#define RADIO_2056_SYN_COM_RC_RXLPF 0xd -#define RADIO_2056_SYN_COM_RC_TXLPF 0xe -#define RADIO_2056_SYN_COM_RC_RXHPF 0xf -#define RADIO_2056_SYN_RESERVED_ADDR16 0x10 -#define RADIO_2056_SYN_RESERVED_ADDR17 0x11 -#define RADIO_2056_SYN_RESERVED_ADDR18 0x12 -#define RADIO_2056_SYN_RESERVED_ADDR19 0x13 -#define RADIO_2056_SYN_RESERVED_ADDR20 0x14 -#define RADIO_2056_SYN_RESERVED_ADDR21 0x15 -#define RADIO_2056_SYN_RESERVED_ADDR22 0x16 -#define RADIO_2056_SYN_RESERVED_ADDR23 0x17 -#define RADIO_2056_SYN_RESERVED_ADDR24 0x18 -#define RADIO_2056_SYN_RESERVED_ADDR25 0x19 -#define RADIO_2056_SYN_RESERVED_ADDR26 0x1a -#define RADIO_2056_SYN_RESERVED_ADDR27 0x1b -#define RADIO_2056_SYN_RESERVED_ADDR28 0x1c -#define RADIO_2056_SYN_RESERVED_ADDR29 0x1d -#define RADIO_2056_SYN_RESERVED_ADDR30 0x1e -#define RADIO_2056_SYN_RESERVED_ADDR31 0x1f -#define RADIO_2056_SYN_GPIO_MASTER1 0x20 -#define RADIO_2056_SYN_GPIO_MASTER2 0x21 -#define RADIO_2056_SYN_TOPBIAS_MASTER 0x22 -#define RADIO_2056_SYN_TOPBIAS_RCAL 0x23 -#define RADIO_2056_SYN_AFEREG 0x24 -#define RADIO_2056_SYN_TEMPPROCSENSE 0x25 -#define RADIO_2056_SYN_TEMPPROCSENSEIDAC 0x26 -#define RADIO_2056_SYN_TEMPPROCSENSERCAL 0x27 -#define RADIO_2056_SYN_LPO 0x28 -#define RADIO_2056_SYN_VDDCAL_MASTER 0x29 -#define RADIO_2056_SYN_VDDCAL_IDAC 0x2a -#define RADIO_2056_SYN_VDDCAL_STATUS 0x2b -#define RADIO_2056_SYN_RCAL_MASTER 0x2c -#define RADIO_2056_SYN_RCAL_CODE_OUT 0x2d -#define RADIO_2056_SYN_RCCAL_CTRL0 0x2e -#define RADIO_2056_SYN_RCCAL_CTRL1 0x2f -#define RADIO_2056_SYN_RCCAL_CTRL2 0x30 -#define RADIO_2056_SYN_RCCAL_CTRL3 0x31 -#define RADIO_2056_SYN_RCCAL_CTRL4 0x32 -#define RADIO_2056_SYN_RCCAL_CTRL5 0x33 -#define RADIO_2056_SYN_RCCAL_CTRL6 0x34 -#define RADIO_2056_SYN_RCCAL_CTRL7 0x35 -#define RADIO_2056_SYN_RCCAL_CTRL8 0x36 -#define RADIO_2056_SYN_RCCAL_CTRL9 0x37 -#define RADIO_2056_SYN_RCCAL_CTRL10 0x38 -#define RADIO_2056_SYN_RCCAL_CTRL11 0x39 -#define RADIO_2056_SYN_ZCAL_SPARE1 0x3a -#define RADIO_2056_SYN_ZCAL_SPARE2 0x3b -#define RADIO_2056_SYN_PLL_MAST1 0x3c -#define RADIO_2056_SYN_PLL_MAST2 0x3d -#define RADIO_2056_SYN_PLL_MAST3 0x3e -#define RADIO_2056_SYN_PLL_BIAS_RESET 0x3f -#define RADIO_2056_SYN_PLL_XTAL0 0x40 -#define RADIO_2056_SYN_PLL_XTAL1 0x41 -#define RADIO_2056_SYN_PLL_XTAL3 0x42 -#define RADIO_2056_SYN_PLL_XTAL4 0x43 -#define RADIO_2056_SYN_PLL_XTAL5 0x44 -#define RADIO_2056_SYN_PLL_XTAL6 0x45 -#define RADIO_2056_SYN_PLL_REFDIV 0x46 -#define RADIO_2056_SYN_PLL_PFD 0x47 -#define RADIO_2056_SYN_PLL_CP1 0x48 -#define RADIO_2056_SYN_PLL_CP2 0x49 -#define RADIO_2056_SYN_PLL_CP3 0x4a -#define RADIO_2056_SYN_PLL_LOOPFILTER1 0x4b -#define RADIO_2056_SYN_PLL_LOOPFILTER2 0x4c -#define RADIO_2056_SYN_PLL_LOOPFILTER3 0x4d -#define RADIO_2056_SYN_PLL_LOOPFILTER4 0x4e -#define RADIO_2056_SYN_PLL_LOOPFILTER5 0x4f -#define RADIO_2056_SYN_PLL_MMD1 0x50 -#define RADIO_2056_SYN_PLL_MMD2 0x51 -#define RADIO_2056_SYN_PLL_VCO1 0x52 -#define RADIO_2056_SYN_PLL_VCO2 0x53 -#define RADIO_2056_SYN_PLL_MONITOR1 0x54 -#define RADIO_2056_SYN_PLL_MONITOR2 0x55 -#define RADIO_2056_SYN_PLL_VCOCAL1 0x56 -#define RADIO_2056_SYN_PLL_VCOCAL2 0x57 -#define RADIO_2056_SYN_PLL_VCOCAL4 0x58 -#define RADIO_2056_SYN_PLL_VCOCAL5 0x59 -#define RADIO_2056_SYN_PLL_VCOCAL6 0x5a -#define RADIO_2056_SYN_PLL_VCOCAL7 0x5b -#define RADIO_2056_SYN_PLL_VCOCAL8 0x5c -#define RADIO_2056_SYN_PLL_VCOCAL9 0x5d -#define RADIO_2056_SYN_PLL_VCOCAL10 0x5e -#define RADIO_2056_SYN_PLL_VCOCAL11 0x5f -#define RADIO_2056_SYN_PLL_VCOCAL12 0x60 -#define RADIO_2056_SYN_PLL_VCOCAL13 0x61 -#define RADIO_2056_SYN_PLL_VREG 0x62 -#define RADIO_2056_SYN_PLL_STATUS1 0x63 -#define RADIO_2056_SYN_PLL_STATUS2 0x64 -#define RADIO_2056_SYN_PLL_STATUS3 0x65 -#define RADIO_2056_SYN_LOGEN_PU0 0x66 -#define RADIO_2056_SYN_LOGEN_PU1 0x67 -#define RADIO_2056_SYN_LOGEN_PU2 0x68 -#define RADIO_2056_SYN_LOGEN_PU3 0x69 -#define RADIO_2056_SYN_LOGEN_PU5 0x6a -#define RADIO_2056_SYN_LOGEN_PU6 0x6b -#define RADIO_2056_SYN_LOGEN_PU7 0x6c -#define RADIO_2056_SYN_LOGEN_PU8 0x6d -#define RADIO_2056_SYN_LOGEN_BIAS_RESET 0x6e -#define RADIO_2056_SYN_LOGEN_RCCR1 0x6f -#define RADIO_2056_SYN_LOGEN_VCOBUF1 0x70 -#define RADIO_2056_SYN_LOGEN_MIXER1 0x71 -#define RADIO_2056_SYN_LOGEN_MIXER2 0x72 -#define RADIO_2056_SYN_LOGEN_BUF1 0x73 -#define RADIO_2056_SYN_LOGENBUF2 0x74 -#define RADIO_2056_SYN_LOGEN_BUF3 0x75 -#define RADIO_2056_SYN_LOGEN_BUF4 0x76 -#define RADIO_2056_SYN_LOGEN_DIV1 0x77 -#define RADIO_2056_SYN_LOGEN_DIV2 0x78 -#define RADIO_2056_SYN_LOGEN_DIV3 0x79 -#define RADIO_2056_SYN_LOGEN_ACL1 0x7a -#define RADIO_2056_SYN_LOGEN_ACL2 0x7b -#define RADIO_2056_SYN_LOGEN_ACL3 0x7c -#define RADIO_2056_SYN_LOGEN_ACL4 0x7d -#define RADIO_2056_SYN_LOGEN_ACL5 0x7e -#define RADIO_2056_SYN_LOGEN_ACL6 0x7f -#define RADIO_2056_SYN_LOGEN_ACLOUT 0x80 -#define RADIO_2056_SYN_LOGEN_ACLCAL1 0x81 -#define RADIO_2056_SYN_LOGEN_ACLCAL2 0x82 -#define RADIO_2056_SYN_LOGEN_ACLCAL3 0x83 -#define RADIO_2056_SYN_CALEN 0x84 -#define RADIO_2056_SYN_LOGEN_PEAKDET1 0x85 -#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR 0x86 -#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 -#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 -#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 -#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8a -#define RADIO_2056_SYN_LOGEN_VCOBUF2 0x8b -#define RADIO_2056_SYN_LOGEN_MIXER3 0x8c -#define RADIO_2056_SYN_LOGEN_BUF5 0x8d -#define RADIO_2056_SYN_LOGEN_BUF6 0x8e -#define RADIO_2056_SYN_LOGEN_CBUFRX1 0x8f -#define RADIO_2056_SYN_LOGEN_CBUFRX2 0x90 -#define RADIO_2056_SYN_LOGEN_CBUFRX3 0x91 -#define RADIO_2056_SYN_LOGEN_CBUFRX4 0x92 -#define RADIO_2056_SYN_LOGEN_CBUFTX1 0x93 -#define RADIO_2056_SYN_LOGEN_CBUFTX2 0x94 -#define RADIO_2056_SYN_LOGEN_CBUFTX3 0x95 -#define RADIO_2056_SYN_LOGEN_CBUFTX4 0x96 -#define RADIO_2056_SYN_LOGEN_CMOSRX1 0x97 -#define RADIO_2056_SYN_LOGEN_CMOSRX2 0x98 -#define RADIO_2056_SYN_LOGEN_CMOSRX3 0x99 -#define RADIO_2056_SYN_LOGEN_CMOSRX4 0x9a -#define RADIO_2056_SYN_LOGEN_CMOSTX1 0x9b -#define RADIO_2056_SYN_LOGEN_CMOSTX2 0x9c -#define RADIO_2056_SYN_LOGEN_CMOSTX3 0x9d -#define RADIO_2056_SYN_LOGEN_CMOSTX4 0x9e -#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9f -#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL 0xa0 -#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL 0xa1 -#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL 0xa2 -#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xa3 -#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xa4 -#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xa5 -#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xa6 -#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xa7 -#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xa8 -#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xa9 -#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xaa -#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xab -#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xac -#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xad -#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xae -#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xaf -#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xb0 -#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xb1 -#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xb2 -#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT 0xb3 -#define RADIO_2056_SYN_LOGEN_CORE_CALVALID 0xb4 -#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID 0xb5 -#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID 0xb6 - -#define RADIO_2056_TX_RESERVED_ADDR0 0x0 -#define RADIO_2056_TX_IDCODE 0x1 -#define RADIO_2056_TX_RESERVED_ADDR2 0x2 -#define RADIO_2056_TX_RESERVED_ADDR3 0x3 -#define RADIO_2056_TX_RESERVED_ADDR4 0x4 -#define RADIO_2056_TX_RESERVED_ADDR5 0x5 -#define RADIO_2056_TX_RESERVED_ADDR6 0x6 -#define RADIO_2056_TX_RESERVED_ADDR7 0x7 -#define RADIO_2056_TX_COM_CTRL 0x8 -#define RADIO_2056_TX_COM_PU 0x9 -#define RADIO_2056_TX_COM_OVR 0xa -#define RADIO_2056_TX_COM_RESET 0xb -#define RADIO_2056_TX_COM_RCAL 0xc -#define RADIO_2056_TX_COM_RC_RXLPF 0xd -#define RADIO_2056_TX_COM_RC_TXLPF 0xe -#define RADIO_2056_TX_COM_RC_RXHPF 0xf -#define RADIO_2056_TX_RESERVED_ADDR16 0x10 -#define RADIO_2056_TX_RESERVED_ADDR17 0x11 -#define RADIO_2056_TX_RESERVED_ADDR18 0x12 -#define RADIO_2056_TX_RESERVED_ADDR19 0x13 -#define RADIO_2056_TX_RESERVED_ADDR20 0x14 -#define RADIO_2056_TX_RESERVED_ADDR21 0x15 -#define RADIO_2056_TX_RESERVED_ADDR22 0x16 -#define RADIO_2056_TX_RESERVED_ADDR23 0x17 -#define RADIO_2056_TX_RESERVED_ADDR24 0x18 -#define RADIO_2056_TX_RESERVED_ADDR25 0x19 -#define RADIO_2056_TX_RESERVED_ADDR26 0x1a -#define RADIO_2056_TX_RESERVED_ADDR27 0x1b -#define RADIO_2056_TX_RESERVED_ADDR28 0x1c -#define RADIO_2056_TX_RESERVED_ADDR29 0x1d -#define RADIO_2056_TX_RESERVED_ADDR30 0x1e -#define RADIO_2056_TX_RESERVED_ADDR31 0x1f -#define RADIO_2056_TX_IQCAL_GAIN_BW 0x20 -#define RADIO_2056_TX_LOFT_FINE_I 0x21 -#define RADIO_2056_TX_LOFT_FINE_Q 0x22 -#define RADIO_2056_TX_LOFT_COARSE_I 0x23 -#define RADIO_2056_TX_LOFT_COARSE_Q 0x24 -#define RADIO_2056_TX_TX_COM_MASTER1 0x25 -#define RADIO_2056_TX_TX_COM_MASTER2 0x26 -#define RADIO_2056_TX_RXIQCAL_TXMUX 0x27 -#define RADIO_2056_TX_TX_SSI_MASTER 0x28 -#define RADIO_2056_TX_IQCAL_VCM_HG 0x29 -#define RADIO_2056_TX_IQCAL_IDAC 0x2a -#define RADIO_2056_TX_TSSI_VCM 0x2b -#define RADIO_2056_TX_TX_AMP_DET 0x2c -#define RADIO_2056_TX_TX_SSI_MUX 0x2d -#define RADIO_2056_TX_TSSIA 0x2e -#define RADIO_2056_TX_TSSIG 0x2f -#define RADIO_2056_TX_TSSI_MISC1 0x30 -#define RADIO_2056_TX_TSSI_MISC2 0x31 -#define RADIO_2056_TX_TSSI_MISC3 0x32 -#define RADIO_2056_TX_PA_SPARE1 0x33 -#define RADIO_2056_TX_PA_SPARE2 0x34 -#define RADIO_2056_TX_INTPAA_MASTER 0x35 -#define RADIO_2056_TX_INTPAA_GAIN 0x36 -#define RADIO_2056_TX_INTPAA_BOOST_TUNE 0x37 -#define RADIO_2056_TX_INTPAA_IAUX_STAT 0x38 -#define RADIO_2056_TX_INTPAA_IAUX_DYN 0x39 -#define RADIO_2056_TX_INTPAA_IMAIN_STAT 0x3a -#define RADIO_2056_TX_INTPAA_IMAIN_DYN 0x3b -#define RADIO_2056_TX_INTPAA_CASCBIAS 0x3c -#define RADIO_2056_TX_INTPAA_PASLOPE 0x3d -#define RADIO_2056_TX_INTPAA_PA_MISC 0x3e -#define RADIO_2056_TX_INTPAG_MASTER 0x3f -#define RADIO_2056_TX_INTPAG_GAIN 0x40 -#define RADIO_2056_TX_INTPAG_BOOST_TUNE 0x41 -#define RADIO_2056_TX_INTPAG_IAUX_STAT 0x42 -#define RADIO_2056_TX_INTPAG_IAUX_DYN 0x43 -#define RADIO_2056_TX_INTPAG_IMAIN_STAT 0x44 -#define RADIO_2056_TX_INTPAG_IMAIN_DYN 0x45 -#define RADIO_2056_TX_INTPAG_CASCBIAS 0x46 -#define RADIO_2056_TX_INTPAG_PASLOPE 0x47 -#define RADIO_2056_TX_INTPAG_PA_MISC 0x48 -#define RADIO_2056_TX_PADA_MASTER 0x49 -#define RADIO_2056_TX_PADA_IDAC 0x4a -#define RADIO_2056_TX_PADA_CASCBIAS 0x4b -#define RADIO_2056_TX_PADA_GAIN 0x4c -#define RADIO_2056_TX_PADA_BOOST_TUNE 0x4d -#define RADIO_2056_TX_PADA_SLOPE 0x4e -#define RADIO_2056_TX_PADG_MASTER 0x4f -#define RADIO_2056_TX_PADG_IDAC 0x50 -#define RADIO_2056_TX_PADG_CASCBIAS 0x51 -#define RADIO_2056_TX_PADG_GAIN 0x52 -#define RADIO_2056_TX_PADG_BOOST_TUNE 0x53 -#define RADIO_2056_TX_PADG_SLOPE 0x54 -#define RADIO_2056_TX_PGAA_MASTER 0x55 -#define RADIO_2056_TX_PGAA_IDAC 0x56 -#define RADIO_2056_TX_PGAA_GAIN 0x57 -#define RADIO_2056_TX_PGAA_BOOST_TUNE 0x58 -#define RADIO_2056_TX_PGAA_SLOPE 0x59 -#define RADIO_2056_TX_PGAA_MISC 0x5a -#define RADIO_2056_TX_PGAG_MASTER 0x5b -#define RADIO_2056_TX_PGAG_IDAC 0x5c -#define RADIO_2056_TX_PGAG_GAIN 0x5d -#define RADIO_2056_TX_PGAG_BOOST_TUNE 0x5e -#define RADIO_2056_TX_PGAG_SLOPE 0x5f -#define RADIO_2056_TX_PGAG_MISC 0x60 -#define RADIO_2056_TX_MIXA_MASTER 0x61 -#define RADIO_2056_TX_MIXA_BOOST_TUNE 0x62 -#define RADIO_2056_TX_MIXG 0x63 -#define RADIO_2056_TX_MIXG_BOOST_TUNE 0x64 -#define RADIO_2056_TX_BB_GM_MASTER 0x65 -#define RADIO_2056_TX_GMBB_GM 0x66 -#define RADIO_2056_TX_GMBB_IDAC 0x67 -#define RADIO_2056_TX_TXLPF_MASTER 0x68 -#define RADIO_2056_TX_TXLPF_RCCAL 0x69 -#define RADIO_2056_TX_TXLPF_RCCAL_OFF0 0x6a -#define RADIO_2056_TX_TXLPF_RCCAL_OFF1 0x6b -#define RADIO_2056_TX_TXLPF_RCCAL_OFF2 0x6c -#define RADIO_2056_TX_TXLPF_RCCAL_OFF3 0x6d -#define RADIO_2056_TX_TXLPF_RCCAL_OFF4 0x6e -#define RADIO_2056_TX_TXLPF_RCCAL_OFF5 0x6f -#define RADIO_2056_TX_TXLPF_RCCAL_OFF6 0x70 -#define RADIO_2056_TX_TXLPF_BW 0x71 -#define RADIO_2056_TX_TXLPF_GAIN 0x72 -#define RADIO_2056_TX_TXLPF_IDAC 0x73 -#define RADIO_2056_TX_TXLPF_IDAC_0 0x74 -#define RADIO_2056_TX_TXLPF_IDAC_1 0x75 -#define RADIO_2056_TX_TXLPF_IDAC_2 0x76 -#define RADIO_2056_TX_TXLPF_IDAC_3 0x77 -#define RADIO_2056_TX_TXLPF_IDAC_4 0x78 -#define RADIO_2056_TX_TXLPF_IDAC_5 0x79 -#define RADIO_2056_TX_TXLPF_IDAC_6 0x7a -#define RADIO_2056_TX_TXLPF_OPAMP_IDAC 0x7b -#define RADIO_2056_TX_TXLPF_MISC 0x7c -#define RADIO_2056_TX_TXSPARE1 0x7d -#define RADIO_2056_TX_TXSPARE2 0x7e -#define RADIO_2056_TX_TXSPARE3 0x7f -#define RADIO_2056_TX_TXSPARE4 0x80 -#define RADIO_2056_TX_TXSPARE5 0x81 -#define RADIO_2056_TX_TXSPARE6 0x82 -#define RADIO_2056_TX_TXSPARE7 0x83 -#define RADIO_2056_TX_TXSPARE8 0x84 -#define RADIO_2056_TX_TXSPARE9 0x85 -#define RADIO_2056_TX_TXSPARE10 0x86 -#define RADIO_2056_TX_TXSPARE11 0x87 -#define RADIO_2056_TX_TXSPARE12 0x88 -#define RADIO_2056_TX_TXSPARE13 0x89 -#define RADIO_2056_TX_TXSPARE14 0x8a -#define RADIO_2056_TX_TXSPARE15 0x8b -#define RADIO_2056_TX_TXSPARE16 0x8c -#define RADIO_2056_TX_STATUS_INTPA_GAIN 0x8d -#define RADIO_2056_TX_STATUS_PAD_GAIN 0x8e -#define RADIO_2056_TX_STATUS_PGA_GAIN 0x8f -#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN 0x90 -#define RADIO_2056_TX_STATUS_TXLPF_BW 0x91 -#define RADIO_2056_TX_STATUS_TXLPF_RC 0x92 -#define RADIO_2056_TX_GMBB_IDAC0 0x93 -#define RADIO_2056_TX_GMBB_IDAC1 0x94 -#define RADIO_2056_TX_GMBB_IDAC2 0x95 -#define RADIO_2056_TX_GMBB_IDAC3 0x96 -#define RADIO_2056_TX_GMBB_IDAC4 0x97 -#define RADIO_2056_TX_GMBB_IDAC5 0x98 -#define RADIO_2056_TX_GMBB_IDAC6 0x99 -#define RADIO_2056_TX_GMBB_IDAC7 0x9a - -#define RADIO_2056_RX_RESERVED_ADDR0 0x0 -#define RADIO_2056_RX_IDCODE 0x1 -#define RADIO_2056_RX_RESERVED_ADDR2 0x2 -#define RADIO_2056_RX_RESERVED_ADDR3 0x3 -#define RADIO_2056_RX_RESERVED_ADDR4 0x4 -#define RADIO_2056_RX_RESERVED_ADDR5 0x5 -#define RADIO_2056_RX_RESERVED_ADDR6 0x6 -#define RADIO_2056_RX_RESERVED_ADDR7 0x7 -#define RADIO_2056_RX_COM_CTRL 0x8 -#define RADIO_2056_RX_COM_PU 0x9 -#define RADIO_2056_RX_COM_OVR 0xa -#define RADIO_2056_RX_COM_RESET 0xb -#define RADIO_2056_RX_COM_RCAL 0xc -#define RADIO_2056_RX_COM_RC_RXLPF 0xd -#define RADIO_2056_RX_COM_RC_TXLPF 0xe -#define RADIO_2056_RX_COM_RC_RXHPF 0xf -#define RADIO_2056_RX_RESERVED_ADDR16 0x10 -#define RADIO_2056_RX_RESERVED_ADDR17 0x11 -#define RADIO_2056_RX_RESERVED_ADDR18 0x12 -#define RADIO_2056_RX_RESERVED_ADDR19 0x13 -#define RADIO_2056_RX_RESERVED_ADDR20 0x14 -#define RADIO_2056_RX_RESERVED_ADDR21 0x15 -#define RADIO_2056_RX_RESERVED_ADDR22 0x16 -#define RADIO_2056_RX_RESERVED_ADDR23 0x17 -#define RADIO_2056_RX_RESERVED_ADDR24 0x18 -#define RADIO_2056_RX_RESERVED_ADDR25 0x19 -#define RADIO_2056_RX_RESERVED_ADDR26 0x1a -#define RADIO_2056_RX_RESERVED_ADDR27 0x1b -#define RADIO_2056_RX_RESERVED_ADDR28 0x1c -#define RADIO_2056_RX_RESERVED_ADDR29 0x1d -#define RADIO_2056_RX_RESERVED_ADDR30 0x1e -#define RADIO_2056_RX_RESERVED_ADDR31 0x1f -#define RADIO_2056_RX_RXIQCAL_RXMUX 0x20 -#define RADIO_2056_RX_RSSI_PU 0x21 -#define RADIO_2056_RX_RSSI_SEL 0x22 -#define RADIO_2056_RX_RSSI_GAIN 0x23 -#define RADIO_2056_RX_RSSI_NB_IDAC 0x24 -#define RADIO_2056_RX_RSSI_WB2I_IDAC_1 0x25 -#define RADIO_2056_RX_RSSI_WB2I_IDAC_2 0x26 -#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1 0x27 -#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2 0x28 -#define RADIO_2056_RX_RSSI_POLE 0x29 -#define RADIO_2056_RX_RSSI_WB1_IDAC 0x2a -#define RADIO_2056_RX_RSSI_MISC 0x2b -#define RADIO_2056_RX_LNAA_MASTER 0x2c -#define RADIO_2056_RX_LNAA_TUNE 0x2d -#define RADIO_2056_RX_LNAA_GAIN 0x2e -#define RADIO_2056_RX_LNA_A_SLOPE 0x2f -#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC 0x30 -#define RADIO_2056_RX_LNAA2_IDAC 0x31 -#define RADIO_2056_RX_LNA1A_MISC 0x32 -#define RADIO_2056_RX_LNAG_MASTER 0x33 -#define RADIO_2056_RX_LNAG_TUNE 0x34 -#define RADIO_2056_RX_LNAG_GAIN 0x35 -#define RADIO_2056_RX_LNA_G_SLOPE 0x36 -#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC 0x37 -#define RADIO_2056_RX_LNAG2_IDAC 0x38 -#define RADIO_2056_RX_LNA1G_MISC 0x39 -#define RADIO_2056_RX_MIXA_MASTER 0x3a -#define RADIO_2056_RX_MIXA_VCM 0x3b -#define RADIO_2056_RX_MIXA_CTRLPTAT 0x3c -#define RADIO_2056_RX_MIXA_LOB_BIAS 0x3d -#define RADIO_2056_RX_MIXA_CORE_IDAC 0x3e -#define RADIO_2056_RX_MIXA_CMFB_IDAC 0x3f -#define RADIO_2056_RX_MIXA_BIAS_AUX 0x40 -#define RADIO_2056_RX_MIXA_BIAS_MAIN 0x41 -#define RADIO_2056_RX_MIXA_BIAS_MISC 0x42 -#define RADIO_2056_RX_MIXA_MAST_BIAS 0x43 -#define RADIO_2056_RX_MIXG_MASTER 0x44 -#define RADIO_2056_RX_MIXG_VCM 0x45 -#define RADIO_2056_RX_MIXG_CTRLPTAT 0x46 -#define RADIO_2056_RX_MIXG_LOB_BIAS 0x47 -#define RADIO_2056_RX_MIXG_CORE_IDAC 0x48 -#define RADIO_2056_RX_MIXG_CMFB_IDAC 0x49 -#define RADIO_2056_RX_MIXG_BIAS_AUX 0x4a -#define RADIO_2056_RX_MIXG_BIAS_MAIN 0x4b -#define RADIO_2056_RX_MIXG_BIAS_MISC 0x4c -#define RADIO_2056_RX_MIXG_MAST_BIAS 0x4d -#define RADIO_2056_RX_TIA_MASTER 0x4e -#define RADIO_2056_RX_TIA_IOPAMP 0x4f -#define RADIO_2056_RX_TIA_QOPAMP 0x50 -#define RADIO_2056_RX_TIA_IMISC 0x51 -#define RADIO_2056_RX_TIA_QMISC 0x52 -#define RADIO_2056_RX_TIA_GAIN 0x53 -#define RADIO_2056_RX_TIA_SPARE1 0x54 -#define RADIO_2056_RX_TIA_SPARE2 0x55 -#define RADIO_2056_RX_BB_LPF_MASTER 0x56 -#define RADIO_2056_RX_AACI_MASTER 0x57 -#define RADIO_2056_RX_RXLPF_IDAC 0x58 -#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 -#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5a -#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL 0x5b -#define RADIO_2056_RX_RXLPF_OUTVCM 0x5c -#define RADIO_2056_RX_RXLPF_INVCM_BODY 0x5d -#define RADIO_2056_RX_RXLPF_CC_OP 0x5e -#define RADIO_2056_RX_RXLPF_GAIN 0x5f -#define RADIO_2056_RX_RXLPF_Q_BW 0x60 -#define RADIO_2056_RX_RXLPF_HP_CORNER_BW 0x61 -#define RADIO_2056_RX_RXLPF_RCCAL_HPC 0x62 -#define RADIO_2056_RX_RXHPF_OFF0 0x63 -#define RADIO_2056_RX_RXHPF_OFF1 0x64 -#define RADIO_2056_RX_RXHPF_OFF2 0x65 -#define RADIO_2056_RX_RXHPF_OFF3 0x66 -#define RADIO_2056_RX_RXHPF_OFF4 0x67 -#define RADIO_2056_RX_RXHPF_OFF5 0x68 -#define RADIO_2056_RX_RXHPF_OFF6 0x69 -#define RADIO_2056_RX_RXHPF_OFF7 0x6a -#define RADIO_2056_RX_RXLPF_RCCAL_LPC 0x6b -#define RADIO_2056_RX_RXLPF_OFF_0 0x6c -#define RADIO_2056_RX_RXLPF_OFF_1 0x6d -#define RADIO_2056_RX_RXLPF_OFF_2 0x6e -#define RADIO_2056_RX_RXLPF_OFF_3 0x6f -#define RADIO_2056_RX_RXLPF_OFF_4 0x70 -#define RADIO_2056_RX_UNUSED 0x71 -#define RADIO_2056_RX_VGA_MASTER 0x72 -#define RADIO_2056_RX_VGA_BIAS 0x73 -#define RADIO_2056_RX_VGA_BIAS_DCCANCEL 0x74 -#define RADIO_2056_RX_VGA_GAIN 0x75 -#define RADIO_2056_RX_VGA_HP_CORNER_BW 0x76 -#define RADIO_2056_RX_VGABUF_BIAS 0x77 -#define RADIO_2056_RX_VGABUF_GAIN_BW 0x78 -#define RADIO_2056_RX_TXFBMIX_A 0x79 -#define RADIO_2056_RX_TXFBMIX_G 0x7a -#define RADIO_2056_RX_RXSPARE1 0x7b -#define RADIO_2056_RX_RXSPARE2 0x7c -#define RADIO_2056_RX_RXSPARE3 0x7d -#define RADIO_2056_RX_RXSPARE4 0x7e -#define RADIO_2056_RX_RXSPARE5 0x7f -#define RADIO_2056_RX_RXSPARE6 0x80 -#define RADIO_2056_RX_RXSPARE7 0x81 -#define RADIO_2056_RX_RXSPARE8 0x82 -#define RADIO_2056_RX_RXSPARE9 0x83 -#define RADIO_2056_RX_RXSPARE10 0x84 -#define RADIO_2056_RX_RXSPARE11 0x85 -#define RADIO_2056_RX_RXSPARE12 0x86 -#define RADIO_2056_RX_RXSPARE13 0x87 -#define RADIO_2056_RX_RXSPARE14 0x88 -#define RADIO_2056_RX_RXSPARE15 0x89 -#define RADIO_2056_RX_RXSPARE16 0x8a -#define RADIO_2056_RX_STATUS_LNAA_GAIN 0x8b -#define RADIO_2056_RX_STATUS_LNAG_GAIN 0x8c -#define RADIO_2056_RX_STATUS_MIXTIA_GAIN 0x8d -#define RADIO_2056_RX_STATUS_RXLPF_GAIN 0x8e -#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN 0x8f -#define RADIO_2056_RX_STATUS_RXLPF_Q 0x90 -#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW 0x91 -#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC 0x92 -#define RADIO_2056_RX_STATUS_RXLPF_RC 0x93 -#define RADIO_2056_RX_STATUS_HPC_RC 0x94 - -/* 2056 bit masks */ -#define RADIO_2056_LNA1_A_PU 0x01 -#define RADIO_2056_LNA2_A_PU 0x02 -#define RADIO_2056_LNA1_G_PU 0x01 -#define RADIO_2056_LNA2_G_PU 0x02 -#define RADIO_2056_MIXA_PU_I 0x01 -#define RADIO_2056_MIXA_PU_Q 0x02 -#define RADIO_2056_MIXA_PU_GM 0x10 -#define RADIO_2056_MIXG_PU_I 0x01 -#define RADIO_2056_MIXG_PU_Q 0x02 -#define RADIO_2056_MIXG_PU_GM 0x10 -#define RADIO_2056_TIA_PU 0x01 -#define RADIO_2056_BB_LPF_PU 0x20 -#define RADIO_2056_W1_PU 0x02 -#define RADIO_2056_W2_PU 0x04 -#define RADIO_2056_NB_PU 0x08 -#define RADIO_2056_RSSI_W1_SEL 0x02 -#define RADIO_2056_RSSI_W2_SEL 0x04 -#define RADIO_2056_RSSI_NB_SEL 0x08 -#define RADIO_2056_VCM_MASK 0x1c -#define RADIO_2056_RSSI_VCM_SHIFT 0x02 - -#endif /* _BCM20XX_H */ diff --git a/release/src-rt/include/bcm_cfg.h b/release/src-rt/include/bcm_cfg.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcm_ndis.h b/release/src-rt/include/bcm_ndis.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcm_xdr.h b/release/src-rt/include/bcm_xdr.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmcdc.h b/release/src-rt/include/bcmcdc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmdefs.h b/release/src-rt/include/bcmdefs.h old mode 100644 new mode 100755 index 8a87c1da69..f506af988c --- a/release/src-rt/include/bcmdefs.h +++ b/release/src-rt/include/bcmdefs.h @@ -283,6 +283,8 @@ typedef struct { * will result in failure of dma map */ #define MAX_DMA_SEGS 8 +#elif defined(__NetBSD__) +#define MAX_DMA_SEGS 16 #else #define MAX_DMA_SEGS 4 #endif @@ -305,9 +307,13 @@ typedef struct { #if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) /* add 40 bytes to allow for extra RPC header and info */ #define BCMEXTRAHDROOM 220 -#else +#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ +#ifdef CTFMAP +#define BCMEXTRAHDROOM 176 +#else /* CTFMAP */ #define BCMEXTRAHDROOM 172 -#endif +#endif /* CTFMAP */ +#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef SDALIGN diff --git a/release/src-rt/include/bcmdevs.h b/release/src-rt/include/bcmdevs.h old mode 100644 new mode 100755 index aefd64767e..2b119168e5 --- a/release/src-rt/include/bcmdevs.h +++ b/release/src-rt/include/bcmdevs.h @@ -128,9 +128,12 @@ #define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ #define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ #define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ -#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ +#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ #define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ #define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ +#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ +#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ +#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ #define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ #define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ @@ -189,6 +192,7 @@ #define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ #define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ #define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ +#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ #define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ #define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ #define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ @@ -221,9 +225,13 @@ #define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ #define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ #define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ +#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ +#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ +#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ +#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ #define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ #define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ - +#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ #define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ #define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ #define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ @@ -266,7 +274,10 @@ #define BCM5357_PKG_ID 11 /* 5357 package id */ #define BCM5356U_PKG_ID 12 /* 5356U package id */ #define BCM53572_PKG_ID 8 /* 53572 package id */ +#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ #define BCM47188_PKG_ID 9 /* 47188 package id */ +#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ +#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ #define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ #define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ #define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ @@ -340,7 +351,7 @@ #define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ #define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ #define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace - * BFL2_BTC3WIRE + * BFL2_BTC3WIRE */ #define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ #define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ @@ -370,7 +381,8 @@ #define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ #define BFL2_EXTLNA_TX 0x08000000 /* Temp boardflag to indicate to */ /* ucode control of eLNA during Tx */ - +#define BFL2_4313_RADIOREG 0x10000000 + /* board rework */ /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ #define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ @@ -629,6 +641,7 @@ #define BCM94319BHEMU3_SSID 0x0563 #define BCM94319SDHMB_SSID 0x058c #define BCM94319SDBREF_SSID 0x05a1 +#define BCM94319USBSDB_SSID 0x05a2 /* 4329 boards */ #define BCM94329AGB_SSID 0X04b9 @@ -681,6 +694,10 @@ #define BCM943228HM4L_SSID 0x0545 #define BCM943228SD_SSID 0x0573 +/* 43239 Boards */ +#define BCM943239MOD_SSID 0x05ac +#define BCM943239REF_SSID 0x05aa + /* 4331 boards */ #define BCM94331X19 0x00D6 /* X19B */ #define BCM94331PCIEBT3Ax_SSID 0x00E4 /* X28 */ @@ -696,6 +713,8 @@ #define BCM94331PCIEDUAL_SSID 0x059B #define BCM94331MCH5_SSID 0x05A9 #define BCM94331PCIEDUALV2_SSID 0x05B7 +#define BCM94331CS_SSID 0x05C6 +#define BCM94331CSAX_SSID 0x00EF /* 53572 Boards */ #define BCM953572BU_SSID 0x058D diff --git a/release/src-rt/include/bcmendian.h b/release/src-rt/include/bcmendian.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmenet47xx.h b/release/src-rt/include/bcmenet47xx.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmenetmib.h b/release/src-rt/include/bcmenetmib.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmenetphy.h b/release/src-rt/include/bcmenetphy.h old mode 100644 new mode 100755 index c4fd212a53..4a83c182d0 --- a/release/src-rt/include/bcmenetphy.h +++ b/release/src-rt/include/bcmenetphy.h @@ -47,9 +47,7 @@ #define LPA_100HALF 0x0080 /* can do 100mbps half-duplex */ #define LPA_100FULL 0x0100 /* can do 100mbps full-duplex */ #define LPA_100BASE4 0x0200 /* can do 100mbps 4k packets */ -#ifndef LPA_RESV #define LPA_RESV 0x1c00 /* unused */ -#endif #define LPA_RFAULT 0x2000 /* link partner faulted */ #define LPA_LPACK 0x4000 /* link partner acked us */ #define LPA_NPAGE 0x8000 /* next page bit */ diff --git a/release/src-rt/include/bcmenetrxh.h b/release/src-rt/include/bcmenetrxh.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmgmacmib.h b/release/src-rt/include/bcmgmacmib.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmgmacrxh.h b/release/src-rt/include/bcmgmacrxh.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmnvram.h b/release/src-rt/include/bcmnvram.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmotp.h b/release/src-rt/include/bcmotp.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmparams.h b/release/src-rt/include/bcmparams.h old mode 100644 new mode 100755 index 7a82211736..c9ed9a32be --- a/release/src-rt/include/bcmparams.h +++ b/release/src-rt/include/bcmparams.h @@ -20,11 +20,11 @@ #ifndef _bcmparams_h_ #define _bcmparams_h_ -#define VLAN_MAXVID 501 /* Max. VLAN ID supported/allowed */ +#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */ #define VLAN_NUMPRIS 8 /* # of prio, start from 0 */ -#define DEV_NUMIFS 32 /* Max. # of devices/interfaces supported */ +#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */ #define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */ diff --git a/release/src-rt/include/bcmperf.h b/release/src-rt/include/bcmperf.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmrobo.h b/release/src-rt/include/bcmrobo.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmsdpcm.h b/release/src-rt/include/bcmsdpcm.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmsrom.h b/release/src-rt/include/bcmsrom.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmsrom_fmt.h b/release/src-rt/include/bcmsrom_fmt.h old mode 100644 new mode 100755 index ae8e718055..6892155091 --- a/release/src-rt/include/bcmsrom_fmt.h +++ b/release/src-rt/include/bcmsrom_fmt.h @@ -373,6 +373,7 @@ #define SROM8_RXGAINERR_5GM 207 #define SROM8_RXGAINERR_5GH 208 #define SROM8_RXGAINERR_5GU 209 +#define SROM8_SUBBAND_PPR 210 #define SROM8_PCIEINGRESS_WAR 211 #define SROM9_SAR 212 diff --git a/release/src-rt/include/bcmsrom_tbl.h b/release/src-rt/include/bcmsrom_tbl.h old mode 100644 new mode 100755 index 004ad59e87..9af58b28a8 --- a/release/src-rt/include/bcmsrom_tbl.h +++ b/release/src-rt/include/bcmsrom_tbl.h @@ -421,6 +421,7 @@ static const sromvar_t pci_sromvars[] = { {"noiselvl5gua0", 0xffffff00, 0, SROM8_NOISELVL_5GU, 0x001f}, {"noiselvl5gua1", 0xffffff00, 0, SROM8_NOISELVL_5GU, 0x03e0}, {"noiselvl5gua2", 0xffffff00, 0, SROM8_NOISELVL_5GU, 0x7c00}, + {"subband5gver", 0xffffff00, 0, SROM8_SUBBAND_PPR, 0x7}, {NULL, 0, 0, 0, 0} }; @@ -499,21 +500,21 @@ static const pavars_t pavars[] = { {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, /* HTPHY PPR_SUBBAND */ - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_VER2, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_VER2, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_VER2, 2, "pa5gllw0a2 pa5gllw1a2 pa5gllw2a2"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_VER2, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_VER2, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_VER2, 2, "pa5glhw0a2 pa5glhw1a2 pa5glhw2a2"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_VER2, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_VER2, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_VER2, 2, "pa5gmlw0a2 pa5gmlw1a2 pa5gmlw2a2"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_VER2, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_VER2, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_VER2, 2, "pa5gmhw0a2 pa5gmhw1a2 pa5gmhw2a2"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_VER2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_VER2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, - {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_VER2, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 2, "pa5gllw0a2 pa5gllw1a2 pa5gllw2a2"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 2, "pa5glhw0a2 pa5glhw1a2 pa5glhw2a2"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 2, "pa5gmlw0a2 pa5gmlw1a2 pa5gmlw2a2"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 2, "pa5gmhw0a2 pa5gmhw1a2 pa5gmhw2a2"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, + {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, /* NPHY */ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, @@ -524,16 +525,16 @@ static const pavars_t pavars[] = { {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, /* NPHY PPR_SUBBAND */ - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLL_VER2, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLL_VER2, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLH_VER2, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLH_VER2, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GML_VER2, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GML_VER2, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GMH_VER2, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GMH_VER2, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH_VER2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH_VER2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GML_5BAND, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GML_5BAND, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH_5BAND, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, + {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH_5BAND, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, /* LPPHY */ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, diff --git a/release/src-rt/include/bcmstdlib.h b/release/src-rt/include/bcmstdlib.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmutils.h b/release/src-rt/include/bcmutils.h old mode 100644 new mode 100755 index 9644a3ec02..cca37db3c6 --- a/release/src-rt/include/bcmutils.h +++ b/release/src-rt/include/bcmutils.h @@ -89,6 +89,9 @@ struct bcmstrbuf { /* osl multi-precedence packet queue */ +#ifndef PKTQ_LEN_DEFAULT +#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ +#endif #ifndef PKTQ_MAX_PREC #define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ #endif diff --git a/release/src-rt/include/bcmwifi.h b/release/src-rt/include/bcmwifi.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bcmwpa.h b/release/src-rt/include/bcmwpa.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/bitfuncs.h b/release/src-rt/include/bitfuncs.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/cfe_osl.h b/release/src-rt/include/cfe_osl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/code_pattern.h b/release/src-rt/include/code_pattern.h deleted file mode 100644 index fd543c536d..0000000000 --- a/release/src-rt/include/code_pattern.h +++ /dev/null @@ -1 +0,0 @@ -#define MODEL_NAME "WRT54G" diff --git a/release/src-rt/include/cyutils.h b/release/src-rt/include/cyutils.h deleted file mode 100644 index 931817d459..0000000000 --- a/release/src-rt/include/cyutils.h +++ /dev/null @@ -1,7 +0,0 @@ -#include "code_pattern.h" - -#define PPTP_VENDOR "Linksys" -#define PPTP_HOSTNAME "" - -#define L2TP_VENDOR "Linksys" -#define L2TP_HOSTNAME MODEL_NAME diff --git a/release/src-rt/include/d11.h b/release/src-rt/include/d11.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/dmemc_core.h b/release/src-rt/include/dmemc_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/epivers.h b/release/src-rt/include/epivers.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/epivers.h.in b/release/src-rt/include/epivers.h.in old mode 100644 new mode 100755 diff --git a/release/src-rt/include/etioctl.h b/release/src-rt/include/etioctl.h old mode 100644 new mode 100755 index e0716f2e75..5cc773f1b0 --- a/release/src-rt/include/etioctl.h +++ b/release/src-rt/include/etioctl.h @@ -53,6 +53,7 @@ */ #define IOV_ET_POWER_SAVE_MODE 1 #define IOV_ET_CLEAR_DUMP 2 +#define IOV_ET_ROBO_DEVID 3 #if defined(linux) || defined(__ECOS) #define SIOCSETCUP (SIOCDEVPRIVATE + ETCUP) @@ -90,6 +91,33 @@ struct txg { #endif /* linux */ +#if defined(__NetBSD__) +#define SIOCSETCUP _IOW('e', 0, struct ifreq) +#define SIOCSETCDOWN _IOW('e', 1, struct ifreq) +#define SIOCSETCLOOP _IOW('e', 2, struct ifreq) +#define SIOCGETCDUMP _IOWR('e', 3, struct ifreq) +#define SIOCSETCSETMSGLEVEL _IOW('e', 4, struct ifreq) +#define SIOCSETCPROMISC _IOW('e', 5, struct ifreq) +#define SIOCSETCTXDOWN _IOW('e', 6, struct ifreq) /* obsolete */ +#define SIOCSETCSPEED _IOW('e', 7, struct ifreq) +#define SIOCTXGEN _IOW('e', 8, struct ifreq) +#define SIOCGETCPHYRD _IOWR('e', 9, struct ifreq) +#define SIOCSETCPHYWR _IOW('e', 10, struct ifreq) +#define SIOCSETCQOS _IOW('e', 11, struct ifreq) +#define SIOCGETCPHYRD2 _IOWR('e', 12, struct ifreq) +#define SIOCSETCPHYWR2 _IOW('e', 13, struct ifreq) +#define SIOCGETCROBORD _IOWR('e', 14, struct ifreq) +#define SIOCSETCROBOWR _IOW('e', 15, struct ifreq) + +/* arg to SIOCTXGEN */ +struct txg { + uint32 num; /* number of frames to send */ + uint32 delay; /* delay in microseconds between sending each */ + uint32 size; /* size of ether frame to send */ + uchar buf[1514]; /* starting ether frame data */ +}; +#endif /* __NetBSD__ */ + /* * custom OID support * diff --git a/release/src-rt/include/flash.h b/release/src-rt/include/flash.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/flashutl.h b/release/src-rt/include/flashutl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/gmac_common.h b/release/src-rt/include/gmac_common.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/gmac_core.h b/release/src-rt/include/gmac_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndarm.h b/release/src-rt/include/hndarm.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndchipc.h b/release/src-rt/include/hndchipc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndcpu.h b/release/src-rt/include/hndcpu.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hnddma.h b/release/src-rt/include/hnddma.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndgige.h b/release/src-rt/include/hndgige.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndjtagdefs.h b/release/src-rt/include/hndjtagdefs.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndmips.h b/release/src-rt/include/hndmips.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndpci.h b/release/src-rt/include/hndpci.h old mode 100644 new mode 100755 index b75a12bf15..fe222664f0 --- a/release/src-rt/include/hndpci.h +++ b/release/src-rt/include/hndpci.h @@ -39,6 +39,8 @@ extern void hndpci_init_cores(si_t *sih); extern void hndpci_arb_park(si_t *sih, uint parkid); extern bool hndpci_is_hostbridge(uint bus, uint dev); extern uint32 hndpci_get_membase(uint bus); +extern void hndpci_deinit(si_t *sih); +extern int hndpci_deinit_pci(si_t *sih, uint coreunit); #define PCI_PARK_NVRAM 0xff diff --git a/release/src-rt/include/hndpmu.h b/release/src-rt/include/hndpmu.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte.h b/release/src-rt/include/hndrte.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_arm.h b/release/src-rt/include/hndrte_arm.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_armtrap.h b/release/src-rt/include/hndrte_armtrap.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_cons.h b/release/src-rt/include/hndrte_cons.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_lbuf.h b/release/src-rt/include/hndrte_lbuf.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_osl.h b/release/src-rt/include/hndrte_osl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndrte_trap.h b/release/src-rt/include/hndrte_trap.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndsoc.h b/release/src-rt/include/hndsoc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/hndtcam.h b/release/src-rt/include/hndtcam.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/libsmbclient.h b/release/src-rt/include/libsmbclient.h new file mode 100755 index 0000000000..81df7f5865 --- /dev/null +++ b/release/src-rt/include/libsmbclient.h @@ -0,0 +1,3170 @@ +/*===================================================================== + Unix SMB/Netbios implementation. + SMB client library API definitions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000 + Copyright (C) John Terpsra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + =====================================================================*/ + +#ifndef SMBCLIENT_H_INCLUDED +#define SMBCLIENT_H_INCLUDED + +#undef DEPRECATED_SMBC_INTERFACE +#if ! defined(__LIBSMBCLIENT_INTERNAL__) && defined(__GNUC__) +# define DEPRECATED_SMBC_INTERFACE __attribute__ ((deprecated)) +#else +# define DEPRECATED_SMBC_INTERFACE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------------------------------------------------------*/ +/* The following are special comments to instruct DOXYGEN (automated + * documentation tool: +*/ +/** \defgroup libsmbclient +*/ +/** \defgroup structure Data Structures Type and Constants +* \ingroup libsmbclient +* Data structures, types, and constants +*/ +/** \defgroup callback Callback function types +* \ingroup libsmbclient +* Callback functions +*/ +/** \defgroup file File Functions +* \ingroup libsmbclient +* Functions used to access individual file contents +*/ +/** \defgroup directory Directory Functions +* \ingroup libsmbclient +* Functions used to access directory entries +*/ +/** \defgroup attribute Attributes Functions +* \ingroup libsmbclient +* Functions used to view or change file and directory attributes +*/ +/** \defgroup print Print Functions +* \ingroup libsmbclient +* Functions used to access printing functionality +*/ +/** \defgroup misc Miscellaneous Functions +* \ingroup libsmbclient +* Functions that don't fit in to other categories +*/ +/*-------------------------------------------------------------------*/ + +/* Make sure we have the following includes for now ... */ +#include +#include +#include +#include +#include + +#define SMBC_BASE_FD 10000 /* smallest file descriptor returned */ + +#define SMBC_WORKGROUP 1 +#define SMBC_SERVER 2 +#define SMBC_FILE_SHARE 3 +#define SMBC_PRINTER_SHARE 4 +#define SMBC_COMMS_SHARE 5 +#define SMBC_IPC_SHARE 6 +#define SMBC_DIR 7 +#define SMBC_FILE 8 +#define SMBC_LINK 9 + +/**@ingroup structure + * Structure that represents a directory entry. + * + */ +struct smbc_dirent +{ + /** Type of entity. + SMBC_WORKGROUP=1, + SMBC_SERVER=2, + SMBC_FILE_SHARE=3, + SMBC_PRINTER_SHARE=4, + SMBC_COMMS_SHARE=5, + SMBC_IPC_SHARE=6, + SMBC_DIR=7, + SMBC_FILE=8, + SMBC_LINK=9,*/ + unsigned int smbc_type; + + /** Length of this smbc_dirent in bytes + */ + unsigned int dirlen; + /** The length of the comment string in bytes (does not include + * null terminator) + */ + unsigned int commentlen; + /** Points to the null terminated comment string + */ + char *comment; + /** The length of the name string in bytes (does not include + * null terminator) + */ + unsigned int namelen; + /** Points to the null terminated name string + */ + char name[1]; +}; + +/* + * Flags for smbc_setxattr() + * Specify a bitwise OR of these, or 0 to add or replace as necessary + */ +#define SMBC_XATTR_FLAG_CREATE 0x1 /* fail if attr already exists */ +#define SMBC_XATTR_FLAG_REPLACE 0x2 /* fail if attr does not exist */ + + +/* + * Mappings of the DOS mode bits, as returned by smbc_getxattr() when the + * attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or + * "system.*") is specified. + */ +#define SMBC_DOS_MODE_READONLY 0x01 +#define SMBC_DOS_MODE_HIDDEN 0x02 +#define SMBC_DOS_MODE_SYSTEM 0x04 +#define SMBC_DOS_MODE_VOLUME_ID 0x08 +#define SMBC_DOS_MODE_DIRECTORY 0x10 +#define SMBC_DOS_MODE_ARCHIVE 0x20 + +/* + * Valid values for the option "open_share_mode", when calling + * smbc_setOptionOpenShareMode() + */ +typedef enum smbc_share_mode +{ + SMBC_SHAREMODE_DENY_DOS = 0, + SMBC_SHAREMODE_DENY_ALL = 1, + SMBC_SHAREMODE_DENY_WRITE = 2, + SMBC_SHAREMODE_DENY_READ = 3, + SMBC_SHAREMODE_DENY_NONE = 4, + SMBC_SHAREMODE_DENY_FCB = 7 +} smbc_share_mode; + + +/** + * Values for option SMB Encryption Level, as set and retrieved with + * smbc_setOptionSmbEncryptionLevel() and smbc_getOptionSmbEncryptionLevel() + */ +typedef enum smbc_smb_encrypt_level +{ + SMBC_ENCRYPTLEVEL_NONE = 0, + SMBC_ENCRYPTLEVEL_REQUEST = 1, + SMBC_ENCRYPTLEVEL_REQUIRE = 2 +} smbc_smb_encrypt_level; + + +/** + * Capabilities set in the f_flag field of struct statvfs, from + * smbc_statvfs(). These may be OR-ed together to reflect a full set of + * available capabilities. + */ +typedef enum smbc_vfs_feature +{ + /* Defined by POSIX or in Linux include files (low-order bits) */ + SMBC_VFS_FEATURE_RDONLY = (1 << 0), + + /* Specific to libsmbclient (high-order bits) */ + SMBC_VFS_FEATURE_DFS = (1 << 28), + SMBC_VFS_FEATURE_CASE_INSENSITIVE = (1 << 29), + SMBC_VFS_FEATURE_NO_UNIXCIFS = (1 << 30) +} smbc_vfs_feature; + +typedef int smbc_bool; + + +#ifndef ENOATTR +# define ENOATTR ENOENT /* No such attribute */ +#endif + + + + +/**@ingroup structure + * Structure that represents a print job. + * + */ +#ifndef _CLIENT_H +struct print_job_info +{ + /** numeric ID of the print job + */ + unsigned short id; + + /** represents print job priority (lower numbers mean higher priority) + */ + unsigned short priority; + + /** Size of the print job + */ + size_t size; + + /** Name of the user that owns the print job + */ + char user[128]; + + /** Name of the print job. This will have no name if an anonymous print + * file was opened. Ie smb://server/printer + */ + char name[128]; + + /** Time the print job was spooled + */ + time_t t; +}; + +typedef struct file_info { + struct cli_state *cli; + uint64_t size; + uint16_t mode; + uid_t uid; + gid_t gid; + /* these times are normally kept in GMT */ + struct timespec mtime_ts; + struct timespec atime_ts; + struct timespec ctime_ts; + char *name; + char short_name[13*3]; /* the *3 is to cope with multi-byte */ +} file_info; + +#endif /* _CLIENT_H */ + + +/**@ingroup structure + * Server handle + */ +typedef struct _SMBCSRV SMBCSRV; + +/**@ingroup structure + * File or directory handle + */ +typedef struct _SMBCFILE SMBCFILE; + +/**@ingroup structure + * File or directory handle + */ +typedef struct _SMBCCTX SMBCCTX; + + +/* + * Flags for SMBCCTX->flags + * + * NEW CODE SHOULD NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE. + * Instead, use: + * smbc_setOptionUseKerberos() + * smbc_getOptionUseKerberos() + * smbc_setOptionFallbackAfterKerberos() + * smbc_getOptionFallbackAFterKerberos() + * smbc_setOptionNoAutoAnonymousLogin() + * smbc_getOptionNoAutoAnonymousLogin() + * smbc_setOptionUseCCache() + * smbc_getOptionUseCCache() + */ +# define SMB_CTX_FLAG_USE_KERBEROS (1 << 0) +# define SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS (1 << 1) +# define SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON (1 << 2) +# define SMB_CTX_FLAG_USE_CCACHE (1 << 3) + + + +/**@ingroup callback + * Authentication callback function type (traditional method) + * + * Type for the the authentication function called by the library to + * obtain authentication credentals + * + * For kerberos support the function should just be called without + * prompting the user for credentials. Which means a simple 'return' + * should work. Take a look at examples/libsmbclient/get_auth_data_fn.h + * and examples/libsmbclient/testbrowse.c. + * + * @param srv Server being authenticated to + * + * @param shr Share being authenticated to + * + * @param wg Pointer to buffer containing a "hint" for the + * workgroup to be authenticated. Should be filled in + * with the correct workgroup if the hint is wrong. + * + * @param wglen The size of the workgroup buffer in bytes + * + * @param un Pointer to buffer containing a "hint" for the + * user name to be use for authentication. Should be + * filled in with the correct workgroup if the hint is + * wrong. + * + * @param unlen The size of the username buffer in bytes + * + * @param pw Pointer to buffer containing to which password + * copied + * + * @param pwlen The size of the password buffer in bytes + * + */ +typedef void (*smbc_get_auth_data_fn)(const char *srv, + const char *shr, + char *wg, int wglen, + char *un, int unlen, + char *pw, int pwlen); +/**@ingroup callback + * Authentication callback function type (method that includes context) + * + * Type for the the authentication function called by the library to + * obtain authentication credentals + * + * For kerberos support the function should just be called without + * prompting the user for credentials. Which means a simple 'return' + * should work. Take a look at examples/libsmbclient/get_auth_data_fn.h + * and examples/libsmbclient/testbrowse.c. + * + * @param c Pointer to the smb context + * + * @param srv Server being authenticated to + * + * @param shr Share being authenticated to + * + * @param wg Pointer to buffer containing a "hint" for the + * workgroup to be authenticated. Should be filled in + * with the correct workgroup if the hint is wrong. + * + * @param wglen The size of the workgroup buffer in bytes + * + * @param un Pointer to buffer containing a "hint" for the + * user name to be use for authentication. Should be + * filled in with the correct workgroup if the hint is + * wrong. + * + * @param unlen The size of the username buffer in bytes + * + * @param pw Pointer to buffer containing to which password + * copied + * + * @param pwlen The size of the password buffer in bytes + * + */ +typedef void (*smbc_get_auth_data_with_context_fn)(SMBCCTX *c, + const char *srv, + const char *shr, + char *wg, int wglen, + char *un, int unlen, + char *pw, int pwlen); + + +/**@ingroup callback + * Print job info callback function type. + * + * @param i pointer to print job information structure + * + */ +typedef void (*smbc_list_print_job_fn)(struct print_job_info *i); + + +/**@ingroup callback + * Check if a server is still good + * + * @param c pointer to smb context + * + * @param srv pointer to server to check + * + * @return 0 when connection is good. 1 on error. + * + */ +typedef int (*smbc_check_server_fn)(SMBCCTX * c, SMBCSRV *srv); + +/**@ingroup callback + * Remove a server if unused + * + * @param c pointer to smb context + * + * @param srv pointer to server to remove + * + * @return 0 on success. 1 on failure. + * + */ +typedef int (*smbc_remove_unused_server_fn)(SMBCCTX * c, SMBCSRV *srv); + + +/**@ingroup callback + * Add a server to the cache system + * + * @param c pointer to smb context + * + * @param srv pointer to server to add + * + * @param server server name + * + * @param share share name + * + * @param workgroup workgroup used to connect + * + * @param username username used to connect + * + * @return 0 on success. 1 on failure. + * + */ +typedef int (*smbc_add_cached_srv_fn) (SMBCCTX * c, SMBCSRV *srv, + const char * server, const char * share, + const char * workgroup, const char * username); + +/**@ingroup callback + * Look up a server in the cache system + * + * @param c pointer to smb context + * + * @param server server name to match + * + * @param share share name to match + * + * @param workgroup workgroup to match + * + * @param username username to match + * + * @return pointer to SMBCSRV on success. NULL on failure. + * + */ +typedef SMBCSRV * (*smbc_get_cached_srv_fn) (SMBCCTX * c, const char * server, + const char * share, const char * workgroup, + const char * username); + +/**@ingroup callback + * Check if a server is still good + * + * @param c pointer to smb context + * + * @param srv pointer to server to remove + * + * @return 0 when found and removed. 1 on failure. + * + */ +typedef int (*smbc_remove_cached_srv_fn)(SMBCCTX * c, SMBCSRV *srv); + + +/**@ingroup callback + * Try to remove all servers from the cache system and disconnect + * + * @param c pointer to smb context + * + * @return 0 when found and removed. 1 on failure. + * + */ +typedef int (*smbc_purge_cached_fn) (SMBCCTX * c); + + + +/***************************************** + * Getters and setters for CONFIGURATION * + *****************************************/ + +/** Get the debug level */ +int +smbc_getDebug(SMBCCTX *c); + +/** Set the debug level */ +void +smbc_setDebug(SMBCCTX *c, int debug); + +/** Get the netbios name used for making connections */ +char * +smbc_getNetbiosName(SMBCCTX *c); + +/** Set the netbios name used for making connections */ +void +smbc_setNetbiosName(SMBCCTX *c, char * netbios_name); + +/** Get the workgroup used for making connections */ +char * +smbc_getWorkgroup(SMBCCTX *c); + +/** Set the workgroup used for making connections */ +void smbc_setWorkgroup(SMBCCTX *c, char * workgroup); + +/** Get the username used for making connections */ +char * +smbc_getUser(SMBCCTX *c); + +/** Set the username used for making connections */ +void +smbc_setUser(SMBCCTX *c, char * user); + +/** + * Get the timeout used for waiting on connections and response data + * (in milliseconds) + */ +int +smbc_getTimeout(SMBCCTX *c); + +/** + * Set the timeout used for waiting on connections and response data + * (in milliseconds) + */ +void +smbc_setTimeout(SMBCCTX *c, int timeout); + + + +/*********************************** + * Getters and setters for OPTIONS * + ***********************************/ + +/** Get whether to log to standard error instead of standard output */ +smbc_bool +smbc_getOptionDebugToStderr(SMBCCTX *c); + +/** Set whether to log to standard error instead of standard output */ +void +smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b); + +/** + * Get whether to use new-style time attribute names, e.g. WRITE_TIME rather + * than the old-style names such as M_TIME. This allows also setting/getting + * CREATE_TIME which was previously unimplemented. (Note that the old C_TIME + * was supposed to be CHANGE_TIME but was confused and sometimes referred to + * CREATE_TIME.) + */ +smbc_bool +smbc_getOptionFullTimeNames(SMBCCTX *c); + +/** + * Set whether to use new-style time attribute names, e.g. WRITE_TIME rather + * than the old-style names such as M_TIME. This allows also setting/getting + * CREATE_TIME which was previously unimplemented. (Note that the old C_TIME + * was supposed to be CHANGE_TIME but was confused and sometimes referred to + * CREATE_TIME.) + */ +void +smbc_setOptionFullTimeNames(SMBCCTX *c, smbc_bool b); + +/** + * Get the share mode to use for files opened with SMBC_open_ctx(). The + * default is SMBC_SHAREMODE_DENY_NONE. + */ +smbc_share_mode +smbc_getOptionOpenShareMode(SMBCCTX *c); + +/** + * Set the share mode to use for files opened with SMBC_open_ctx(). The + * default is SMBC_SHAREMODE_DENY_NONE. + */ +void +smbc_setOptionOpenShareMode(SMBCCTX *c, smbc_share_mode share_mode); + +/** Retrieve a previously saved user data handle */ +void * +smbc_getOptionUserData(SMBCCTX *c); + +/** Save a user data handle */ +void +smbc_setOptionUserData(SMBCCTX *c, void *user_data); + +/** Get the encoded value for encryption level. */ +smbc_smb_encrypt_level +smbc_getOptionSmbEncryptionLevel(SMBCCTX *c); + +/** Set the encoded value for encryption level. */ +void +smbc_setOptionSmbEncryptionLevel(SMBCCTX *c, smbc_smb_encrypt_level level); + +/** + * Get whether to treat file names as case-sensitive if we can't determine + * when connecting to the remote share whether the file system is case + * sensitive. This defaults to FALSE since it's most likely that if we can't + * retrieve the file system attributes, it's a very old file system that does + * not support case sensitivity. + */ +smbc_bool +smbc_getOptionCaseSensitive(SMBCCTX *c); + +/** + * Set whether to treat file names as case-sensitive if we can't determine + * when connecting to the remote share whether the file system is case + * sensitive. This defaults to FALSE since it's most likely that if we can't + * retrieve the file system attributes, it's a very old file system that does + * not support case sensitivity. + */ +void +smbc_setOptionCaseSensitive(SMBCCTX *c, smbc_bool b); + + +/** + * Get from how many local master browsers should the list of workgroups be + * retrieved. It can take up to 12 minutes or longer after a server becomes a + * local master browser, for it to have the entire browse list (the list of + * workgroups/domains) from an entire network. Since a client never knows + * which local master browser will be found first, the one which is found + * first and used to retrieve a browse list may have an incomplete or empty + * browse list. By requesting the browse list from multiple local master + * browsers, a more complete list can be generated. For small networks (few + * workgroups), it is recommended that this value be set to 0, causing the + * browse lists from all found local master browsers to be retrieved and + * merged. For networks with many workgroups, a suitable value for this + * variable is probably somewhere around 3. (Default: 3). + */ +int +smbc_getOptionBrowseMaxLmbCount(SMBCCTX *c); + +/** + * Set from how many local master browsers should the list of workgroups be + * retrieved. It can take up to 12 minutes or longer after a server becomes a + * local master browser, for it to have the entire browse list (the list of + * workgroups/domains) from an entire network. Since a client never knows + * which local master browser will be found first, the one which is found + * first and used to retrieve a browse list may have an incomplete or empty + * browse list. By requesting the browse list from multiple local master + * browsers, a more complete list can be generated. For small networks (few + * workgroups), it is recommended that this value be set to 0, causing the + * browse lists from all found local master browsers to be retrieved and + * merged. For networks with many workgroups, a suitable value for this + * variable is probably somewhere around 3. (Default: 3). + */ +void +smbc_setOptionBrowseMaxLmbCount(SMBCCTX *c, int count); + +/** + * Get whether to url-encode readdir entries. + * + * There is a difference in the desired return strings from + * smbc_readdir() depending upon whether the filenames are to + * be displayed to the user, or whether they are to be + * appended to the path name passed to smbc_opendir() to call + * a further smbc_ function (e.g. open the file with + * smbc_open()). In the former case, the filename should be + * in "human readable" form. In the latter case, the smbc_ + * functions expect a URL which must be url-encoded. Those + * functions decode the URL. If, for example, smbc_readdir() + * returned a file name of "abc%20def.txt", passing a path + * with this file name attached to smbc_open() would cause + * smbc_open to attempt to open the file "abc def.txt" since + * the %20 is decoded into a space. + * + * Set this option to True if the names returned by + * smbc_readdir() should be url-encoded such that they can be + * passed back to another smbc_ call. Set it to False if the + * names returned by smbc_readdir() are to be presented to the + * user. + * + * For backwards compatibility, this option defaults to False. + */ +smbc_bool +smbc_getOptionUrlEncodeReaddirEntries(SMBCCTX *c); + +/** + * Set whether to url-encode readdir entries. + * + * There is a difference in the desired return strings from + * smbc_readdir() depending upon whether the filenames are to + * be displayed to the user, or whether they are to be + * appended to the path name passed to smbc_opendir() to call + * a further smbc_ function (e.g. open the file with + * smbc_open()). In the former case, the filename should be + * in "human readable" form. In the latter case, the smbc_ + * functions expect a URL which must be url-encoded. Those + * functions decode the URL. If, for example, smbc_readdir() + * returned a file name of "abc%20def.txt", passing a path + * with this file name attached to smbc_open() would cause + * smbc_open to attempt to open the file "abc def.txt" since + * the %20 is decoded into a space. + * + * Set this option to True if the names returned by + * smbc_readdir() should be url-encoded such that they can be + * passed back to another smbc_ call. Set it to False if the + * names returned by smbc_readdir() are to be presented to the + * user. + * + * For backwards compatibility, this option defaults to False. + */ +void +smbc_setOptionUrlEncodeReaddirEntries(SMBCCTX *c, smbc_bool b); + +/** + * Get whether to use the same connection for all shares on a server. + * + * Some Windows versions appear to have a limit to the number + * of concurrent SESSIONs and/or TREE CONNECTions. In + * one-shot programs (i.e. the program runs and then quickly + * ends, thereby shutting down all connections), it is + * probably reasonable to establish a new connection for each + * share. In long-running applications, the limitation can be + * avoided by using only a single connection to each server, + * and issuing a new TREE CONNECT when the share is accessed. + */ +smbc_bool +smbc_getOptionOneSharePerServer(SMBCCTX *c); + +/** + * Set whether to use the same connection for all shares on a server. + * + * Some Windows versions appear to have a limit to the number + * of concurrent SESSIONs and/or TREE CONNECTions. In + * one-shot programs (i.e. the program runs and then quickly + * ends, thereby shutting down all connections), it is + * probably reasonable to establish a new connection for each + * share. In long-running applications, the limitation can be + * avoided by using only a single connection to each server, + * and issuing a new TREE CONNECT when the share is accessed. + */ +void +smbc_setOptionOneSharePerServer(SMBCCTX *c, smbc_bool b); + +/** Get whether to enable use of kerberos */ +smbc_bool +smbc_getOptionUseKerberos(SMBCCTX *c); + +/** Set whether to enable use of kerberos */ +void +smbc_setOptionUseKerberos(SMBCCTX *c, smbc_bool b); + +/** Get whether to fallback after kerberos */ +smbc_bool +smbc_getOptionFallbackAfterKerberos(SMBCCTX *c); + +/** Set whether to fallback after kerberos */ +void +smbc_setOptionFallbackAfterKerberos(SMBCCTX *c, smbc_bool b); + +/** Get whether to automatically select anonymous login */ +smbc_bool +smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c); + +/** Set whether to automatically select anonymous login */ +void +smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b); + +/** Get whether to enable use of the winbind ccache */ +smbc_bool +smbc_getOptionUseCCache(SMBCCTX *c); + +/** Set whether to enable use of the winbind ccache */ +void +smbc_setOptionUseCCache(SMBCCTX *c, smbc_bool b); + + + +/************************************* + * Getters and setters for FUNCTIONS * + *************************************/ + +/** Get the function for obtaining authentication data */ +smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c); + +/** Set the function for obtaining authentication data */ +void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn); + +/** Get the new-style authentication function which includes the context. */ +smbc_get_auth_data_with_context_fn +smbc_getFunctionAuthDataWithContext(SMBCCTX *c); + +/** Set the new-style authentication function which includes the context. */ +void +smbc_setFunctionAuthDataWithContext(SMBCCTX *c, + smbc_get_auth_data_with_context_fn fn); + +/** Get the function for checking if a server is still good */ +smbc_check_server_fn smbc_getFunctionCheckServer(SMBCCTX *c); + +/** Set the function for checking if a server is still good */ +void smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn); + +/** Get the function for removing a server if unused */ +smbc_remove_unused_server_fn smbc_getFunctionRemoveUnusedServer(SMBCCTX *c); + +/** Set the function for removing a server if unused */ +void smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, + smbc_remove_unused_server_fn fn); + +/** Get the function for adding a cached server */ +smbc_add_cached_srv_fn smbc_getFunctionAddCachedServer(SMBCCTX *c); + +/** Set the function for adding a cached server */ +void smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn); + +/** Get the function for server cache lookup */ +smbc_get_cached_srv_fn smbc_getFunctionGetCachedServer(SMBCCTX *c); + +/** Set the function for server cache lookup */ +void smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn); + +/** Get the function for server cache removal */ +smbc_remove_cached_srv_fn smbc_getFunctionRemoveCachedServer(SMBCCTX *c); + +/** Set the function for server cache removal */ +void smbc_setFunctionRemoveCachedServer(SMBCCTX *c, + smbc_remove_cached_srv_fn fn); + +/** + * Get the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +smbc_purge_cached_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c); + +/** + * Set the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, + smbc_purge_cached_fn fn); + +/** Get the function to store private data of the server cache */ +struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c); + +/** Set the function to store private data of the server cache */ +void smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache); + + + +/***************************************************************** + * Callable functions for files. * + * Each callable has a function signature typedef, a declaration * + * for the getter, and a declaration for the setter. * + *****************************************************************/ + +typedef SMBCFILE * (*smbc_open_fn)(SMBCCTX *c, + const char *fname, + int flags, + mode_t mode); +smbc_open_fn smbc_getFunctionOpen(SMBCCTX *c); +void smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn); + +typedef SMBCFILE * (*smbc_creat_fn)(SMBCCTX *c, + const char *path, + mode_t mode); +smbc_creat_fn smbc_getFunctionCreat(SMBCCTX *c); +void smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn); + +typedef ssize_t (*smbc_read_fn)(SMBCCTX *c, + SMBCFILE *file, + void *buf, + size_t count); +smbc_read_fn smbc_getFunctionRead(SMBCCTX *c); +void smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn); + +typedef ssize_t (*smbc_write_fn)(SMBCCTX *c, + SMBCFILE *file, + const void *buf, + size_t count); +smbc_write_fn smbc_getFunctionWrite(SMBCCTX *c); +void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn); + +typedef int (*smbc_unlink_fn)(SMBCCTX *c, + const char *fname); +smbc_unlink_fn smbc_getFunctionUnlink(SMBCCTX *c); +void smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn); + +typedef int (*smbc_rename_fn)(SMBCCTX *ocontext, + const char *oname, + SMBCCTX *ncontext, + const char *nname); +smbc_rename_fn smbc_getFunctionRename(SMBCCTX *c); +void smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn); + +typedef off_t (*smbc_lseek_fn)(SMBCCTX *c, + SMBCFILE * file, + off_t offset, + int whence); +smbc_lseek_fn smbc_getFunctionLseek(SMBCCTX *c); +void smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn); + +typedef int (*smbc_stat_fn)(SMBCCTX *c, + const char *fname, + struct stat *st); +smbc_stat_fn smbc_getFunctionStat(SMBCCTX *c); +void smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn); + +typedef int (*smbc_fstat_fn)(SMBCCTX *c, + SMBCFILE *file, + struct stat *st); +smbc_fstat_fn smbc_getFunctionFstat(SMBCCTX *c); +void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn); + +typedef int (*smbc_statvfs_fn)(SMBCCTX *c, + char *path, + struct statvfs *st); +smbc_statvfs_fn smbc_getFunctionStatVFS(SMBCCTX *c); +void smbc_setFunctionStatVFS(SMBCCTX *c, smbc_statvfs_fn fn); + +typedef int (*smbc_fstatvfs_fn)(SMBCCTX *c, + SMBCFILE *file, + struct statvfs *st); +smbc_fstatvfs_fn smbc_getFunctionFstatVFS(SMBCCTX *c); +void smbc_setFunctionFstatVFS(SMBCCTX *c, smbc_fstatvfs_fn fn); + +typedef int (*smbc_ftruncate_fn)(SMBCCTX *c, + SMBCFILE *f, + off_t size); +smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c); +void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn); + +typedef int (*smbc_close_fn)(SMBCCTX *c, + SMBCFILE *file); +smbc_close_fn smbc_getFunctionClose(SMBCCTX *c); +void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn); + + + +/***************************************************************** + * Callable functions for directories. * + * Each callable has a function signature typedef, a declaration * + * for the getter, and a declaration for the setter. * + *****************************************************************/ + +typedef SMBCFILE * (*smbc_opendir_fn)(SMBCCTX *c, + const char *fname); +smbc_opendir_fn smbc_getFunctionOpendir(SMBCCTX *c); +void smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn); + +typedef int (*smbc_closedir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_closedir_fn smbc_getFunctionClosedir(SMBCCTX *c); +void smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn); + +typedef struct smbc_dirent * (*smbc_readdir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_readdir_fn smbc_getFunctionReaddir(SMBCCTX *c); +void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn); + +typedef int (*smbc_getdents_fn)(SMBCCTX *c, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count); +smbc_getdents_fn smbc_getFunctionGetdents(SMBCCTX *c); +void smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn); + +typedef int (*smbc_mkdir_fn)(SMBCCTX *c, + const char *fname, + mode_t mode); +smbc_mkdir_fn smbc_getFunctionMkdir(SMBCCTX *c); +void smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn); + +typedef int (*smbc_rmdir_fn)(SMBCCTX *c, + const char *fname); +smbc_rmdir_fn smbc_getFunctionRmdir(SMBCCTX *c); +void smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn); + +typedef off_t (*smbc_telldir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_telldir_fn smbc_getFunctionTelldir(SMBCCTX *c); +void smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn); + +typedef int (*smbc_lseekdir_fn)(SMBCCTX *c, + SMBCFILE *dir, + off_t offset); +smbc_lseekdir_fn smbc_getFunctionLseekdir(SMBCCTX *c); +void smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn); + +typedef int (*smbc_fstatdir_fn)(SMBCCTX *c, + SMBCFILE *dir, + struct stat *st); +smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c); +void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn); + + + +/***************************************************************** + * Callable functions applicable to both files and directories. * + * Each callable has a function signature typedef, a declaration * + * for the getter, and a declaration for the setter. * + *****************************************************************/ + +typedef int (*smbc_chmod_fn)(SMBCCTX *c, + const char *fname, + mode_t mode); +smbc_chmod_fn smbc_getFunctionChmod(SMBCCTX *c); +void smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn); + +typedef int (*smbc_utimes_fn)(SMBCCTX *c, + const char *fname, + struct timeval *tbuf); +smbc_utimes_fn smbc_getFunctionUtimes(SMBCCTX *c); +void smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn); + +typedef int (*smbc_setxattr_fn)(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags); +smbc_setxattr_fn smbc_getFunctionSetxattr(SMBCCTX *c); +void smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn); + +typedef int (*smbc_getxattr_fn)(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size); +smbc_getxattr_fn smbc_getFunctionGetxattr(SMBCCTX *c); +void smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn); + +typedef int (*smbc_removexattr_fn)(SMBCCTX *context, + const char *fname, + const char *name); +smbc_removexattr_fn smbc_getFunctionRemovexattr(SMBCCTX *c); +void smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn); + +typedef int (*smbc_listxattr_fn)(SMBCCTX *context, + const char *fname, + char *list, + size_t size); +smbc_listxattr_fn smbc_getFunctionListxattr(SMBCCTX *c); +void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn); + + + +/***************************************************************** + * Callable functions for printing. * + * Each callable has a function signature typedef, a declaration * + * for the getter, and a declaration for the setter. * + *****************************************************************/ + +typedef int (*smbc_print_file_fn)(SMBCCTX *c_file, + const char *fname, + SMBCCTX *c_print, + const char *printq); +smbc_print_file_fn smbc_getFunctionPrintFile(SMBCCTX *c); +void smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn); + +typedef SMBCFILE * (*smbc_open_print_job_fn)(SMBCCTX *c, + const char *fname); +smbc_open_print_job_fn smbc_getFunctionOpenPrintJob(SMBCCTX *c); +void smbc_setFunctionOpenPrintJob(SMBCCTX *c, + smbc_open_print_job_fn fn); + +typedef int (*smbc_list_print_jobs_fn)(SMBCCTX *c, + const char *fname, + smbc_list_print_job_fn fn); +smbc_list_print_jobs_fn smbc_getFunctionListPrintJobs(SMBCCTX *c); +void smbc_setFunctionListPrintJobs(SMBCCTX *c, + smbc_list_print_jobs_fn fn); + +typedef int (*smbc_unlink_print_job_fn)(SMBCCTX *c, + const char *fname, + int id); +smbc_unlink_print_job_fn smbc_getFunctionUnlinkPrintJob(SMBCCTX *c); +void smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, + smbc_unlink_print_job_fn fn); + + +/**@ingroup misc + * Create a new SBMCCTX (a context). + * + * Must be called before the context is passed to smbc_context_init() + * + * @return The given SMBCCTX pointer on success, NULL on error with errno set: + * - ENOMEM Out of memory + * + * @see smbc_free_context(), smbc_init_context() + * + * @note Do not forget to smbc_init_context() the returned SMBCCTX pointer ! + */ +SMBCCTX * smbc_new_context(void); + +/**@ingroup misc + * Delete a SBMCCTX (a context) acquired from smbc_new_context(). + * + * The context will be deleted if possible. + * + * @param context A pointer to a SMBCCTX obtained from smbc_new_context() + * + * @param shutdown_ctx If 1, all connections and files will be closed even if they are busy. + * + * + * @return Returns 0 on succes. Returns 1 on failure with errno set: + * - EBUSY Server connections are still used, Files are open or cache + * could not be purged + * - EBADF context == NULL + * + * @see smbc_new_context() + * + * @note It is advised to clean up all the contexts with shutdown_ctx set to 1 + * just before exit()'ing. When shutdown_ctx is 0, this function can be + * use in periodical cleanup functions for example. + */ +int smbc_free_context(SMBCCTX * context, int shutdown_ctx); + + +/**@ingroup misc + * + * @deprecated. Use smbc_setOption*() functions instead. + */ +void +smbc_option_set(SMBCCTX *context, + char *option_name, + ... /* option_value */); + +/* + * @deprecated. Use smbc_getOption*() functions instead. + */ +void * +smbc_option_get(SMBCCTX *context, + char *option_name); + +/**@ingroup misc + * Initialize a SBMCCTX (a context). + * + * Must be called before using any SMBCCTX API function + * + * @param context A pointer to a SMBCCTX obtained from smbc_new_context() + * + * @return A pointer to the given SMBCCTX on success, + * NULL on error with errno set: + * - EBADF NULL context given + * - ENOMEM Out of memory + * - ENOENT The smb.conf file would not load + * + * @see smbc_new_context() + * + * @note my_context = smbc_init_context(smbc_new_context()) + * is perfectly safe, but it might leak memory on + * smbc_context_init() failure. Avoid this. + * You'll have to call smbc_free_context() yourself + * on failure. + */ + +SMBCCTX * smbc_init_context(SMBCCTX * context); + +/**@ingroup misc + * Initialize the samba client library. + * + * Must be called before using any of the smbclient API function + * + * @param fn The function that will be called to obtaion + * authentication credentials. + * + * @param debug Allows caller to set the debug level. Can be + * changed in smb.conf file. Allows caller to set + * debugging if no smb.conf. + * + * @return 0 on success, < 0 on error with errno set: + * - ENOMEM Out of memory + * - ENOENT The smb.conf file would not load + * + */ + +int smbc_init(smbc_get_auth_data_fn fn, int debug); + +/**@ingroup misc + * Set or retrieve the compatibility library's context pointer + * + * @param context New context to use, or NULL. If a new context is provided, + * it must have allocated with smbc_new_context() and + * initialized with smbc_init_context(), followed, optionally, + * by some manual changes to some of the non-internal fields. + * + * @return The old context. + * + * @see smbc_new_context(), smbc_init_context(), smbc_init() + * + * @note This function may be called prior to smbc_init() to force + * use of the next context without any internal calls to + * smbc_new_context() or smbc_init_context(). It may also + * be called after smbc_init() has already called those two + * functions, to replace the existing context with a new one. + * Care should be taken, in this latter case, to ensure that + * the server cache and any data allocated by the + * authentication functions have been freed, if necessary. + */ + +SMBCCTX * smbc_set_context(SMBCCTX * new_context); + +/**@ingroup file + * Open a file on an SMB server. + * + * @param furl The smb url of the file to be opened. + * + * @param flags Is one of O_RDONLY, O_WRONLY or O_RDWR which + * request opening the file read-only,write-only + * or read/write. flags may also be bitwise-or'd with + * one or more of the following: + * O_CREAT - If the file does not exist it will be + * created. + * O_EXCL - When used with O_CREAT, if the file + * already exists it is an error and the open will + * fail. + * O_TRUNC - If the file already exists it will be + * truncated. + * O_APPEND The file is opened in append mode + * + * @param mode mode specifies the permissions to use if a new + * file is created. It is modified by the + * process's umask in the usual way: the permissions + * of the created file are (mode & ~umask) + * + * Not currently use, but there for future use. + * We will map this to SYSTEM, HIDDEN, etc bits + * that reverses the mapping that smbc_fstat does. + * + * @return Valid file handle, < 0 on error with errno set: + * - ENOMEM Out of memory + * - EINVAL if an invalid parameter passed, like no + * file, or smbc_init not called. + * - EEXIST pathname already exists and O_CREAT and + * O_EXCL were used. + * - EISDIR pathname refers to a directory and + * the access requested involved writing. + * - EACCES The requested access to the file is not + * allowed + * - ENODEV The requested share does not exist + * - ENOTDIR A file on the path is not a directory + * - ENOENT A directory component in pathname does + * not exist. + * + * @see smbc_creat() + * + * @note This call uses an underlying routine that may create + * a new connection to the server specified in the URL. + * If the credentials supplied in the URL, or via the + * auth_fn in the smbc_init call, fail, this call will + * try again with an empty username and password. This + * often gets mapped to the guest account on some machines. + */ + +int smbc_open(const char *furl, int flags, mode_t mode); + +/**@ingroup file + * Create a file on an SMB server. + * + * Same as calling smbc_open() with flags = O_CREAT|O_WRONLY|O_TRUNC + * + * @param furl The smb url of the file to be created + * + * @param mode mode specifies the permissions to use if a new + * file is created. It is modified by the + * process's umask in the usual way: the permissions + * of the created file are (mode & ~umask) + * + * NOTE, the above is not true. We are dealing with + * an SMB server, which has no concept of a umask! + * + * @return Valid file handle, < 0 on error with errno set: + * - ENOMEM Out of memory + * - EINVAL if an invalid parameter passed, like no + * file, or smbc_init not called. + * - EEXIST pathname already exists and O_CREAT and + * O_EXCL were used. + * - EISDIR pathname refers to a directory and + * the access requested involved writing. + * - EACCES The requested access to the file is not + * allowed + * - ENOENT A directory component in pathname does + * not exist. + * - ENODEV The requested share does not exist. + * @see smbc_open() + * + */ + +int smbc_creat(const char *furl, mode_t mode); + +/**@ingroup file + * Read from a file using an opened file handle. + * + * @param fd Open file handle from smbc_open() or smbc_creat() + * + * @param buf Pointer to buffer to recieve read data + * + * @param bufsize Size of buf in bytes + * + * @return Number of bytes read; + * 0 upon EOF; + * < 0 on error, with errno set: + * - EISDIR fd refers to a directory + * - EBADF fd is not a valid file descriptor or + * is not open for reading. + * - EINVAL fd is attached to an object which is + * unsuitable for reading, or no buffer passed or + * smbc_init not called. + * + * @see smbc_open(), smbc_write() + * + */ +ssize_t smbc_read(int fd, void *buf, size_t bufsize); + + +/**@ingroup file + * Write to a file using an opened file handle. + * + * @param fd Open file handle from smbc_open() or smbc_creat() + * + * @param buf Pointer to buffer to recieve read data + * + * @param bufsize Size of buf in bytes + * + * @return Number of bytes written, < 0 on error with errno set: + * - EISDIR fd refers to a directory. + * - EBADF fd is not a valid file descriptor or + * is not open for reading. + * - EINVAL fd is attached to an object which is + * unsuitable for reading, or no buffer passed or + * smbc_init not called. + * + * @see smbc_open(), smbc_read() + * + */ +ssize_t smbc_write(int fd, const void *buf, size_t bufsize); + + +/**@ingroup file + * Seek to a specific location in a file. + * + * @param fd Open file handle from smbc_open() or smbc_creat() + * + * @param offset Offset in bytes from whence + * + * @param whence A location in the file: + * - SEEK_SET The offset is set to offset bytes from + * the beginning of the file + * - SEEK_CUR The offset is set to current location + * plus offset bytes. + * - SEEK_END The offset is set to the size of the + * file plus offset bytes. + * + * @return Upon successful completion, lseek returns the + * resulting offset location as measured in bytes + * from the beginning of the file. Otherwise, a value + * of (off_t)-1 is returned and errno is set to + * indicate the error: + * - EBADF Fildes is not an open file descriptor. + * - EINVAL Whence is not a proper value or smbc_init + * not called. + * + * @todo Are all the whence values really supported? + * + * @todo Are errno values complete and correct? + */ +off_t smbc_lseek(int fd, off_t offset, int whence); + + +/**@ingroup file + * Close an open file handle. + * + * @param fd The file handle to close + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF fd isn't a valid open file descriptor + * - EINVAL smbc_init() failed or has not been called + * + * @see smbc_open(), smbc_creat() + */ +int smbc_close(int fd); + + +/**@ingroup directory + * Unlink (delete) a file or directory. + * + * @param furl The smb url of the file to delete + * + * @return 0 on success, < 0 on error with errno set: + * - EACCES or EPERM Write access to the directory + * containing pathname is not allowed or one + * of the directories in pathname did not allow + * search (execute) permission + * - ENOENT A directory component in pathname does + * not exist + * - EINVAL NULL was passed in the file param or + * smbc_init not called. + * - EACCES You do not have access to the file + * - ENOMEM Insufficient kernel memory was available + * + * @see smbc_rmdir()s + * + * @todo Are errno values complete and correct? + */ +int smbc_unlink(const char *furl); + + +/**@ingroup directory + * Rename or move a file or directory. + * + * @param ourl The original smb url (source url) of file or + * directory to be moved + * + * @param nurl The new smb url (destination url) of the file + * or directory after the move. Currently nurl must + * be on the same share as ourl. + * + * @return 0 on success, < 0 on error with errno set: + * - EISDIR nurl is an existing directory, but ourl is + * not a directory. + * - EEXIST nurl is a non-empty directory, + * i.e., contains entries other than "." and ".." + * - EINVAL The new url contained a path prefix + * of the old, or, more generally, an attempt was + * made to make a directory a subdirectory of itself + * or smbc_init not called. + * - ENOTDIR A component used as a directory in ourl + * or nurl path is not, in fact, a directory. Or, + * ourl is a directory, and newpath exists but is not + * a directory. + * - EACCES or EPERM Write access to the directory + * containing ourl or nurl is not allowed for the + * process's effective uid, or one of the + * directories in ourl or nurl did not allow search + * (execute) permission, or ourl was a directory + * and did not allow write permission. + * - ENOENT A directory component in ourl or nurl + * does not exist. + * - EXDEV Rename across shares not supported. + * - ENOMEM Insufficient kernel memory was available. + * - EEXIST The target file, nurl, already exists. + * + * + * @todo Are we going to support copying when urls are not on the same + * share? I say no... NOTE. I agree for the moment. + * + */ +int smbc_rename(const char *ourl, const char *nurl); + + +/**@ingroup directory + * Open a directory used to obtain directory entries. + * + * @param durl The smb url of the directory to open + * + * @return Valid directory handle. < 0 on error with errno set: + * - EACCES Permission denied. + * - EINVAL A NULL file/URL was passed, or the URL would + * not parse, or was of incorrect form or smbc_init not + * called. + * - ENOENT durl does not exist, or name is an + * - ENOMEM Insufficient memory to complete the + * operation. + * - ENOTDIR name is not a directory. + * - EPERM the workgroup could not be found. + * - ENODEV the workgroup or server could not be found. + * + * @see smbc_getdents(), smbc_readdir(), smbc_closedir() + * + */ +int smbc_opendir(const char *durl); + + +/**@ingroup directory + * Close a directory handle opened by smbc_opendir(). + * + * @param dh Directory handle to close + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF dh is an invalid directory handle + * + * @see smbc_opendir() + */ +int smbc_closedir(int dh); + + +/**@ingroup directory + * Get multiple directory entries. + * + * smbc_getdents() reads as many dirent structures from the an open + * directory handle into a specified memory area as will fit. + * + * @param dh Valid directory as returned by smbc_opendir() + * + * @param dirp pointer to buffer that will receive the directory + * entries. + * + * @param count The size of the dirp buffer in bytes + * + * @returns If any dirents returned, return will indicate the + * total size. If there were no more dirents available, + * 0 is returned. < 0 indicates an error. + * - EBADF Invalid directory handle + * - EINVAL Result buffer is too small or smbc_init + * not called. + * - ENOENT No such directory. + * @see , smbc_dirent, smbc_readdir(), smbc_open() + * + * @todo Are errno values complete and correct? + * + * @todo Add example code so people know how to parse buffers. + */ +int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count); + + +/**@ingroup directory + * Get a single directory entry. + * + * @param dh Valid directory as returned by smbc_opendir() + * + * @return A pointer to a smbc_dirent structure, or NULL if an + * error occurs or end-of-directory is reached: + * - EBADF Invalid directory handle + * - EINVAL smbc_init() failed or has not been called + * + * @see smbc_dirent, smbc_getdents(), smbc_open() + */ +struct smbc_dirent* smbc_readdir(unsigned int dh); + + +/**@ingroup directory + * Get the current directory offset. + * + * smbc_telldir() may be used in conjunction with smbc_readdir() and + * smbc_lseekdir(). + * + * @param dh Valid directory as returned by smbc_opendir() + * + * @return The current location in the directory stream or -1 + * if an error occur. The current location is not + * an offset. Becuase of the implementation, it is a + * handle that allows the library to find the entry + * later. + * - EBADF dh is not a valid directory handle + * - EINVAL smbc_init() failed or has not been called + * - ENOTDIR if dh is not a directory + * + * @see smbc_readdir() + * + */ +off_t smbc_telldir(int dh); + + +/**@ingroup directory + * lseek on directories. + * + * smbc_lseekdir() may be used in conjunction with smbc_readdir() and + * smbc_telldir(). (rewind by smbc_lseekdir(fd, NULL)) + * + * @param fd Valid directory as returned by smbc_opendir() + * + * @param offset The offset (as returned by smbc_telldir). Can be + * NULL, in which case we will rewind + * + * @return 0 on success, -1 on failure + * - EBADF dh is not a valid directory handle + * - ENOTDIR if dh is not a directory + * - EINVAL offset did not refer to a valid dirent or + * smbc_init not called. + * + * @see smbc_telldir() + * + * + * @todo In what does the reture and errno values mean? + */ +int smbc_lseekdir(int fd, off_t offset); + +/**@ingroup directory + * Create a directory. + * + * @param durl The url of the directory to create + * + * @param mode Specifies the permissions to use. It is modified + * by the process's umask in the usual way: the + * permissions of the created file are (mode & ~umask). + * + * @return 0 on success, < 0 on error with errno set: + * - EEXIST directory url already exists + * - EACCES The parent directory does not allow write + * permission to the process, or one of the directories + * - ENOENT A directory component in pathname does not + * exist. + * - EINVAL NULL durl passed or smbc_init not called. + * - ENOMEM Insufficient memory was available. + * + * @see smbc_rmdir() + * + */ +int smbc_mkdir(const char *durl, mode_t mode); + + +/**@ingroup directory + * Remove a directory. + * + * @param durl The smb url of the directory to remove + * + * @return 0 on success, < 0 on error with errno set: + * - EACCES or EPERM Write access to the directory + * containing pathname was not allowed. + * - EINVAL durl is NULL or smbc_init not called. + * - ENOENT A directory component in pathname does not + * exist. + * - ENOTEMPTY directory contains entries. + * - ENOMEM Insufficient kernel memory was available. + * + * @see smbc_mkdir(), smbc_unlink() + * + * @todo Are errno values complete and correct? + */ +int smbc_rmdir(const char *durl); + + +/**@ingroup attribute + * Get information about a file or directory. + * + * @param url The smb url to get information for + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct stat information. + * + * @return 0 on success, < 0 on error with errno set: + * - ENOENT A component of the path file_name does not + * exist. + * - EINVAL a NULL url was passed or smbc_init not called. + * - EACCES Permission denied. + * - ENOMEM Out of memory + * - ENOTDIR The target dir, url, is not a directory. + * + * @see Unix stat() + * + */ +int smbc_stat(const char *url, struct stat *st); + + +/**@ingroup attribute + * Get file information via an file descriptor. + * + * @param fd Open file handle from smbc_open() or smbc_creat() + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct stat information. + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + * + * @see smbc_stat(), Unix stat() + * + */ +int smbc_fstat(int fd, struct stat *st); + + +/**@ingroup attribute + * Get file system information for a specified path. + * + * @param url The smb url to get information for + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct statvfs information. + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + * + * @see Unix fstatvfs() + * + */ +int +smbc_statvfs(char *url, + struct statvfs *st); + +/**@ingroup attribute + * Get file system information via an file descriptor. + * + * @param fd Open file handle from smbc_open(), smbc_creat(), + * or smbc_opendir() + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct statvfs information. + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + * + * @see Unix fstatvfs() + * + */ +int +smbc_fstatvfs(int fd, + struct statvfs *st); + + +/**@ingroup attribute + * Truncate a file given a file descriptor + * + * @param fd Open file handle from smbc_open() or smbc_creat() + * + * @param size size to truncate the file to + * + * @return 0 on success, < 0 on error with errno set: + * - EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + * + * @see , Unix ftruncate() + * + */ +int smbc_ftruncate(int fd, off_t size); + + +/**@ingroup attribute + * Change the permissions of a file. + * + * @param url The smb url of the file or directory to change + * permissions of + * + * @param mode The permissions to set: + * - Put good explaination of permissions here! + * + * @return 0 on success, < 0 on error with errno set: + * - EPERM The effective UID does not match the owner + * of the file, and is not zero + * - ENOENT The file does not exist. + * - ENOMEM Insufficient was available. + * - ENOENT file or directory does not exist + * + * @todo Actually implement this fuction? + * + * @todo Are errno values complete and correct? + */ +int smbc_chmod(const char *url, mode_t mode); + +/** + * @ingroup attribute + * Change the last modification time on a file + * + * @param url The smb url of the file or directory to change + * the modification time of + * + * @param tbuf An array of two timeval structures which contains, + * respectively, the desired access and modification times. + * NOTE: Only the tv_sec field off each timeval structure is + * used. The tv_usec (microseconds) portion is ignored. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - EPERM Permission was denied. + * + */ +int smbc_utimes(const char *url, struct timeval *tbuf); + +#ifdef HAVE_UTIME_H +/** + * @ingroup attribute + * Change the last modification time on a file + * + * @param url The smb url of the file or directory to change + * the modification time of + * + * @param utbuf A pointer to a utimebuf structure which contains the + * desired access and modification times. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * + */ +int smbc_utime(const char *fname, struct utimbuf *utbuf); +#endif + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param url The smb url of the file or directory to set extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_setxattr(const char *url, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list). The + * POSIX function which this maps to would act on a symbolic link rather than + * acting on what the symbolic link points to, but with no symbolic links in + * SMB file systems, this function is functionally identical to + * smbc_setxattr(). + * + * @param url The smb url of the file or directory to set extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_lsetxattr(const char *url, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Set extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be changed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter should contain a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value The value to be assigned to the specified attribute name. + * This buffer should contain only the attribute value if the + * name was of the "system.nt_sec_desc." + * form. If the name was of the "system.nt_sec_desc.*" form + * then a complete security descriptor, with name:value pairs + * separated by tabs, commas, or newlines (not spaces!), + * should be provided in this value buffer. A complete + * security descriptor will contain one or more entries + * selected from the following: + * + * REVISION: + * OWNER: + * GROUP: + * ACL::// + * + * The revision of the ACL specifies the internal Windows NT + * ACL revision for the security descriptor. If not specified + * it defaults to 1. Using values other than 1 may cause + * strange behaviour. + * + * The owner and group specify the owner and group sids for + * the object. If the attribute name (either '*+' with a + * complete security descriptor, or individual 'owner+' or + * 'group+' attribute names) ended with a plus sign, the + * specified name is resolved to a SID value, using the + * server on which the file or directory resides. Otherwise, + * the value should be provided in SID-printable format as + * S-1-x-y-z, and is used directly. The + * associated with the ACL: attribute should be provided + * similarly. + * + * @param size The number of the bytes of data in the value buffer + * + * @param flags A bit-wise OR of zero or more of the following: + * SMBC_XATTR_FLAG_CREATE - + * fail if the named attribute already exists + * SMBC_XATTR_FLAG_REPLACE - + * fail if the attribute does not already exist + * + * If neither flag is specified, the specified attributes + * will be added or replace existing attributes of the same + * name, as necessary. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note Attribute names are compared in a case-insensitive + * fashion. All of the following are equivalent, although + * the all-lower-case name is the preferred format: + * system.nt_sec_desc.owner + * SYSTEM.NT_SEC_DESC.OWNER + * sYsTeM.nt_sEc_desc.owNER + * + */ +int smbc_fsetxattr(int fd, + const char *name, + const void *value, + size_t size, + int flags); + + +/**@ingroup attribute + * Get extended attributes for a file. + * + * @param url The smb url of the file or directory to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_getxattr(const char *url, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Get extended attributes for a file. The POSIX function which this maps to + * would act on a symbolic link rather than acting on what the symbolic link + * points to, but with no symbolic links in SMB file systems, this function + * is functionally identical to smbc_getxattr(). + * + * @param url The smb url of the file or directory to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_lgetxattr(const char *url, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Get extended attributes for a file. + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be retrieved. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @param value A pointer to a buffer in which the value of the specified + * attribute will be placed (unless size is zero). + * + * @param size The size of the buffer pointed to by value. This parameter + * may also be zero, in which case the size of the buffer + * required to hold the attribute value will be returned, + * but nothing will be placed into the value buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * or one of the parameters is not of a correct + * form + * - ENOMEM No memory was available for internal needs + * - EEXIST If the attribute already exists and the flag + * SMBC_XATTR_FLAG_CREAT was specified + * - ENOATTR If the attribute does not exist and the flag + * SMBC_XATTR_FLAG_REPLACE was specified + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_fgetxattr(int fd, + const char *name, + const void *value, + size_t size); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param url The smb url of the file or directory to remove the extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_removexattr(const char *url, + const char *name); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) The POSIX + * function which this maps to would act on a symbolic link rather than acting + * on what the symbolic link points to, but with no symbolic links in SMB file + * systems, this function is functionally identical to smbc_removexattr(). + * + * @param url The smb url of the file or directory to remove the extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_lremovexattr(const char *url, + const char *name); + + +/**@ingroup attribute + * Remove extended attributes for a file. This is used for modifying a file's + * security descriptor (i.e. owner, group, and access control list) + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param name The name of an attribute to be removed. Names are of + * one of the following forms: + * + * system.nt_sec_desc. + * system.nt_sec_desc.* + * system.nt_sec_desc.*+ + * + * where is one of: + * + * revision + * owner + * owner+ + * group + * group+ + * acl: + * acl+: + * + * In the forms "system.nt_sec_desc.*" and + * "system.nt_sec_desc.*+", the asterisk and plus signs are + * literal, i.e. the string is provided exactly as shown, and + * the value parameter will return a complete security + * descriptor with name:value pairs separated by tabs, + * commas, or newlines (not spaces!). + * + * The plus sign ('+') indicates that SIDs should be mapped + * to names. Without the plus sign, SIDs are not mapped; + * rather they are simply converted to a string format. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + */ +int smbc_fremovexattr(int fd, + const char *name); + + +/**@ingroup attribute + * List the supported extended attribute names associated with a file + * + * @param url The smb url of the file or directory to list the extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of whether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_listxattr(const char *url, + char *list, + size_t size); + +/**@ingroup attribute + * List the supported extended attribute names associated with a file The + * POSIX function which this maps to would act on a symbolic link rather than + * acting on what the symbolic link points to, but with no symbolic links in + * SMB file systems, this function is functionally identical to + * smbc_listxattr(). + * + * @param url The smb url of the file or directory to list the extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of wether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_llistxattr(const char *url, + char *list, + size_t size); + +/**@ingroup attribute + * List the supported extended attribute names associated with a file + * + * @param fd A file descriptor associated with an open file (as + * previously returned by smbc_open(), to get extended + * attributes for. + * + * @param list A pointer to a buffer in which the list of attributes for + * the specified file or directory will be placed (unless + * size is zero). + * + * @param size The size of the buffer pointed to by list. This parameter + * may also be zero, in which case the size of the buffer + * required to hold all of the attribute names will be + * returned, but nothing will be placed into the list buffer. + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL The client library is not properly initialized + * - ENOMEM No memory was available for internal needs + * - EPERM Permission was denied. + * - ENOTSUP The referenced file system does not support + * extended attributes + * + * @note This function always returns all attribute names supported + * by NT file systems, regardless of wether the referenced + * file system supports extended attributes (e.g. a Windows + * 2000 machine supports extended attributes if NTFS is used, + * but not if FAT is used, and Windows 98 doesn't support + * extended attributes at all. Whether this is a feature or + * a bug is yet to be decided. + */ +int smbc_flistxattr(int fd, + char *list, + size_t size); + +/**@ingroup print + * Print a file given the name in fname. It would be a URL ... + * + * @param fname The URL of a file on a remote SMB server that the + * caller wants printed + * + * @param printq The URL of the print share to print the file to. + * + * @return 0 on success, < 0 on error with errno set: + * + * - EINVAL fname or printq was NULL or smbc_init not + * not called. + * and errors returned by smbc_open + * + */ +int smbc_print_file(const char *fname, const char *printq); + +/**@ingroup print + * Open a print file that can be written to by other calls. This simply + * does an smbc_open call after checking if there is a file name on the + * URI. If not, a temporary name is added ... + * + * @param fname The URL of the print share to print to? + * + * @returns A file handle for the print file if successful. + * Returns -1 if an error ocurred and errno has the values + * - EINVAL fname was NULL or smbc_init not called. + * - all errors returned by smbc_open + * + */ +int smbc_open_print_job(const char *fname); + +/**@ingroup print + * List the print jobs on a print share, for the moment, pass a callback + * + * @param purl The url of the print share to list the jobs of + * + * @param fn Callback function the receives printjob info + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL fname was NULL or smbc_init not called + * - EACCES ??? + */ +int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn); + +/**@ingroup print + * Delete a print job + * + * @param purl Url of the print share + * + * @param id The id of the job to delete + * + * @return 0 on success, < 0 on error with errno set: + * - EINVAL fname was NULL or smbc_init not called + * + * @todo what errno values are possible here? + */ +int smbc_unlink_print_job(const char *purl, int id); + +/**@ingroup callback + * Remove a server from the cached server list it's unused. + * + * @param context pointer to smb context + * + * @param srv pointer to server to remove + * + * @return On success, 0 is returned. 1 is returned if the server could not + * be removed. Also useable outside libsmbclient. + */ +int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv); + +int smbc_parse_path(const char *purl, char *pWorkgroup, char *pServer, char *pShare, char *pPath); +int smbc_check_connectivity(char *puri); +int smbc_server_check_creds( + const char *server, + const char *share, + char *workgroup, + char *username, + char *password); +#ifdef __cplusplus +} +#endif + +/**@ingroup directory + * Convert strings of %xx to their single character equivalent. + * + * @param dest A pointer to a buffer in which the resulting decoded + * string should be placed. This may be a pointer to the + * same buffer as src_segment. + * + * @param src A pointer to the buffer containing the URL to be decoded. + * Any %xx sequences herein are converted to their single + * character equivalent. Each 'x' must be a valid hexadecimal + * digit, or that % sequence is left undecoded. + * + * @param max_dest_len + * The size of the buffer pointed to by dest_segment. + * + * @return The number of % sequences which could not be converted + * due to lack of two following hexadecimal digits. + */ +#ifdef __cplusplus +extern "C" { +#endif +int +smbc_urldecode(char *dest, char * src, size_t max_dest_len); +#ifdef __cplusplus +} +#endif + + +/* + * Convert any characters not specifically allowed in a URL into their %xx + * equivalent. + * + * @param dest A pointer to a buffer in which the resulting encoded + * string should be placed. Unlike smbc_urldecode(), this + * must be a buffer unique from src. + * + * @param src A pointer to the buffer containing the string to be encoded. + * Any character not specifically allowed in a URL is converted + * into its hexadecimal value and encoded as %xx. + * + * @param max_dest_len + * The size of the buffer pointed to by dest_segment. + * + * @returns The remaining buffer length. + */ +#ifdef __cplusplus +extern "C" { +#endif +int +smbc_urlencode(char * dest, char * src, int max_dest_len); +#ifdef __cplusplus +} +#endif + + +/**@ingroup directory + * Return the version of the linked Samba code, and thus the version of the + * libsmbclient code. + * + * @return The version string. + */ +#ifdef __cplusplus +extern "C" { +#endif +const char * +smbc_version(void); +#ifdef __cplusplus +} +#endif + +/**@ingroup misc + * Set the users credentials globally so they can be used for DFS + * referrals. Probably best to use this function in the smbc_get_auth_data_fn + * callback. + * + * @param workgroup Workgroup of the user. + * + * @param user Username of user. + * + * @param password Password of user. + * + * @param use_kerberos Whether to use Kerberos + * + * @param signing_state One of these strings (all equivalents on same line): + * "off", "no", "false" + * "on", "yes", "true", "auto" + * "force", "required", "forced" + */ + +void +smbc_set_credentials(const char *workgroup, + const char *user, + const char *password, + smbc_bool use_kerberos, + const char *signing_state); + +/* + * Wrapper around smbc_set_credentials. + * Used to set correct credentials that will + * be used to connect to DFS target share + * in libsmbclient + */ + +void +smbc_set_credentials_with_fallback(SMBCCTX *ctx, + const char *workgroup, + const char *user, + const char *password); + + +/** + * @ingroup threads + * + * Initialize for threads using the Posix Threads (pthread) + * implementation. This is a built-in implementation, avoiding the need to + * implement the component functions of the thread interface. If this function + * is used, it is not necessary to call smbc_thread_impl(). + * + * @return {void} + */ +void +smbc_thread_posix(void); + +/** + * @ingroup threads + * + * Initialize for an arbitrary thread implementation. The caller should + * provide, as parameters, pointers to functions to implement the requisite + * low-level thread functionality. A function must be provided for each + * parameter; none may be null. + * + * If the thread implementation is POSIX Threads (pthreads), then the much + * simpler smbc_thread_pthread() function may be used instead of this one. + * + * @param create_mutex + * Create a mutex. This function should expect three parameters: lockname, + * pplock, and location. It should create a unique mutex for each unique + * lockname it is provided, and return the mutex identifier in *pplock. The + * location parameter can be used for debugging, as it contains the + * compiler-provided __location__ of the call. + * + * @param destroy_mutex + * Destroy a mutex. This function should expect two parameters: plock and + * location. It should destroy the mutex associated with the identifier + * plock. The location parameter can be used for debugging, as it contains + * the compiler-provided __location__ of the call. + * + * @param lock_mutex + * Lock a mutex. This function should expect three parameters: plock, + * lock_type, and location. The mutex aassociated with identifier plock + * should be locked if lock_type is 1, and unlocked if lock_type is 2. The + * location parameter can be used for debugging, as it contains the + * compiler-provided __location__ of the call. + * + * @param create_tls + * Create thread local storage. This function should expect three + * parameters: keyname, ppkey, and location. It should allocate an + * implementation-specific amount of memory and assign the pointer to that + * allocated memory to *ppkey. The location parameter can be used for + * debugging, as it contains the compiler-provided __location__ of the + * call. This function should return 0 upon success, non-zero upon failure. + * + * @param destroy_tls + * Destroy thread local storage. This function should expect two parameters: + * ppkey and location. The ppkey parameter points to a variable containing a + * thread local storage key previously provided by the create_tls + * function. The location parameter can be used for debugging, as it + * contains the compiler-provided __location__ of the call. + * + * @param set_tls + * Set a thread local storage variable's value. This function should expect + * three parameters: pkey, pval, and location. The pkey parameter is a + * thread local storage key previously provided by the create_tls + * function. The (void *) pval parameter contains the value to be placed in + * the thread local storage variable identified by pkey. The location + * parameter can be used for debugging, as it contains the compiler-provided + * __location__ of the call. This function should return 0 upon success; + * non-zero otherwise. + * + * @param get_tls + * Retrieve a thread local storage variable's value. This function should + * expect two parameters: pkey and location. The pkey parameter is a thread + * local storage key previously provided by the create_tls function, and + * which has previously been used in a call to the set_tls function to + * initialize a thread local storage variable. The location parameter can be + * used for debugging, as it contains the compiler-provided __location__ of + * the call. This function should return the (void *) value stored in the + * variable identified by pkey. + * + * @return {void} + */ +void +smbc_thread_impl( + /* Mutex functions. */ + int (*create_mutex)(const char *lockname, + void **pplock, + const char *location), + void (*destroy_mutex)(void *plock, + const char *location), + int (*lock_mutex)(void *plock, + int lock_type, + const char *location), + + /* Thread local storage. */ + int (*create_tls)(const char *keyname, + void **ppkey, + const char *location), + void (*destroy_tls)(void **ppkey, + const char *location), + int (*set_tls)(void *pkey, + const void *pval, + const char *location), + void *(*get_tls)(void *pkey, + const char *location) + ); + + + +/** + * @ingroup structure + * Structure that contains a client context information + * This structure is known as SMBCCTX + * + * DO NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE! The data in the context + * structure should all be considered private to the library. It remains here + * only for backward compatibility. + * + * See the comments herein for use of the setter and getter functions which + * should now be used for manipulating these values. New features, functions, + * etc., are not added here but rather in _internal where they are not + * directly visible to applications. This makes it much easier to maintain + * ABI compatibility. + */ +struct _SMBCCTX +{ + /** + * debug level + * + * DEPRECATED: + * Use smbc_getDebug() and smbc_setDebug() + */ + int debug DEPRECATED_SMBC_INTERFACE; + + /** + * netbios name used for making connections + * + * DEPRECATED: + * Use smbc_getNetbiosName() and smbc_setNetbiosName() + */ + char * netbios_name DEPRECATED_SMBC_INTERFACE; + + /** + * workgroup name used for making connections + * + * DEPRECATED: + * Use smbc_getWorkgroup() and smbc_setWorkgroup() + */ + char * workgroup DEPRECATED_SMBC_INTERFACE; + + /** + * username used for making connections + * + * DEPRECATED: + * Use smbc_getUser() and smbc_setUser() + */ + char * user DEPRECATED_SMBC_INTERFACE; + + /** + * timeout used for waiting on connections / response data (in + * milliseconds) + * + * DEPRECATED: + * Use smbc_getTimeout() and smbc_setTimeout() + */ + int timeout DEPRECATED_SMBC_INTERFACE; + + /** + * callable functions for files: + * For usage and return values see the SMBC_* functions + * + * DEPRECATED: + * + * Use smbc_getFunction*() and smbc_setFunction*(), e.g. + * smbc_getFunctionOpen(), smbc_setFunctionUnlink(), etc. + */ + smbc_open_fn open DEPRECATED_SMBC_INTERFACE; + smbc_creat_fn creat DEPRECATED_SMBC_INTERFACE; + smbc_read_fn read DEPRECATED_SMBC_INTERFACE; + smbc_write_fn write DEPRECATED_SMBC_INTERFACE; + smbc_unlink_fn unlink DEPRECATED_SMBC_INTERFACE; + smbc_rename_fn rename DEPRECATED_SMBC_INTERFACE; + smbc_lseek_fn lseek DEPRECATED_SMBC_INTERFACE; + smbc_stat_fn stat DEPRECATED_SMBC_INTERFACE; + smbc_fstat_fn fstat DEPRECATED_SMBC_INTERFACE; +#if 0 /* internal */ + smbc_ftruncate_fn ftruncate_fn; +#endif + smbc_close_fn close_fn DEPRECATED_SMBC_INTERFACE; + smbc_opendir_fn opendir DEPRECATED_SMBC_INTERFACE; + smbc_closedir_fn closedir DEPRECATED_SMBC_INTERFACE; + smbc_readdir_fn readdir DEPRECATED_SMBC_INTERFACE; + smbc_getdents_fn getdents DEPRECATED_SMBC_INTERFACE; + smbc_mkdir_fn mkdir DEPRECATED_SMBC_INTERFACE; + smbc_rmdir_fn rmdir DEPRECATED_SMBC_INTERFACE; + smbc_telldir_fn telldir DEPRECATED_SMBC_INTERFACE; + smbc_lseekdir_fn lseekdir DEPRECATED_SMBC_INTERFACE; + smbc_fstatdir_fn fstatdir DEPRECATED_SMBC_INTERFACE; + smbc_chmod_fn chmod DEPRECATED_SMBC_INTERFACE; + smbc_utimes_fn utimes DEPRECATED_SMBC_INTERFACE; + smbc_setxattr_fn setxattr DEPRECATED_SMBC_INTERFACE; + smbc_getxattr_fn getxattr DEPRECATED_SMBC_INTERFACE; + smbc_removexattr_fn removexattr DEPRECATED_SMBC_INTERFACE; + smbc_listxattr_fn listxattr DEPRECATED_SMBC_INTERFACE; + + /* Printing-related functions */ + smbc_print_file_fn print_file DEPRECATED_SMBC_INTERFACE; + smbc_open_print_job_fn open_print_job DEPRECATED_SMBC_INTERFACE; + smbc_list_print_jobs_fn list_print_jobs DEPRECATED_SMBC_INTERFACE; + smbc_unlink_print_job_fn unlink_print_job DEPRECATED_SMBC_INTERFACE; + + /* + ** Callbacks + * + * DEPRECATED: + * + * See the comment above each field, for the getter and setter + * functions that should now be used. + */ + struct _smbc_callbacks + { + /** + * authentication function callback: called upon auth requests + * + * DEPRECATED: + * Use smbc_getFunctionAuthData(), smbc_setFunctionAuthData() + */ + smbc_get_auth_data_fn auth_fn DEPRECATED_SMBC_INTERFACE; + + /** + * check if a server is still good + * + * DEPRECATED: + * Use smbc_getFunctionCheckServer(), + * smbc_setFunctionCheckServer() + */ + smbc_check_server_fn check_server_fn DEPRECATED_SMBC_INTERFACE; + + /** + * remove a server if unused + * + * DEPRECATED: + * Use smbc_getFunctionRemoveUnusedServer(), + * smbc_setFunctionCheckServer() + */ + smbc_remove_unused_server_fn remove_unused_server_fn DEPRECATED_SMBC_INTERFACE; + + /** Cache subsystem + * + * For an example cache system see + * samba/source/libsmb/libsmb_cache.c + * + * Cache subsystem * functions follow. + */ + + /** + * server cache addition + * + * DEPRECATED: + * Use smbc_getFunctionAddCachedServer(), + * smbc_setFunctionAddCachedServer() + */ + smbc_add_cached_srv_fn add_cached_srv_fn DEPRECATED_SMBC_INTERFACE; + + /** + * server cache lookup + * + * DEPRECATED: + * Use smbc_getFunctionGetCachedServer(), + * smbc_setFunctionGetCachedServer() + */ + smbc_get_cached_srv_fn get_cached_srv_fn DEPRECATED_SMBC_INTERFACE; + + /** + * server cache removal + * + * DEPRECATED: + * Use smbc_getFunctionRemoveCachedServer(), + * smbc_setFunctionRemoveCachedServer() + */ + smbc_remove_cached_srv_fn remove_cached_srv_fn DEPRECATED_SMBC_INTERFACE; + + /** + * server cache purging, try to remove all cached servers + * (disconnect) + * + * DEPRECATED: + * Use smbc_getFunctionPurgeCachedServers(), + * smbc_setFunctionPurgeCachedServers() + */ + smbc_purge_cached_fn purge_cached_fn DEPRECATED_SMBC_INTERFACE; + } callbacks; + + /** + * Space where the private data of the server cache used to be + * + * DEPRECATED: + * Use smbc_getServerCacheData(), smbc_setServerCacheData() + */ + void * reserved DEPRECATED_SMBC_INTERFACE; + + /* + * Very old configuration options. + * + * DEPRECATED: + * Use one of the following functions instead: + * smbc_setOptionUseKerberos() + * smbc_getOptionUseKerberos() + * smbc_setOptionFallbackAfterKerberos() + * smbc_getOptionFallbackAfterKerberos() + * smbc_setOptionNoAutoAnonymousLogin() + * smbc_getOptionNoAutoAnonymousLogin() + */ + int flags DEPRECATED_SMBC_INTERFACE; + + /** + * user options selections that apply to this session + * + * NEW OPTIONS ARE NOT ADDED HERE! + * + * DEPRECATED: + * To set and retrieve options, use the smbc_setOption*() and + * smbc_getOption*() functions. + */ + struct _smbc_options { + int browse_max_lmb_count DEPRECATED_SMBC_INTERFACE; + int urlencode_readdir_entries DEPRECATED_SMBC_INTERFACE; + int one_share_per_server DEPRECATED_SMBC_INTERFACE; + } options DEPRECATED_SMBC_INTERFACE; + + /** INTERNAL DATA + * do _NOT_ touch this from your program ! + */ + struct SMBC_internal_data * internal; +}; + +#if 1 +/*============================================================*/ +//#ifdef LIGHTTPD_INCLUDE +//#ifdef HAVE_LIBSMBCLIENT_H +#if defined(LIGHTTPD_INCLUDE)||defined(HAVE_LIBSMBCLIENT_H) + +#define HAVE_IMMEDIATE_STRUCTURES +#if defined(HAVE_IMMEDIATE_STRUCTURES) +typedef struct {uint32_t v;} NTSTATUS; +#define NT_STATUS(x) ((NTSTATUS) { x }) +#define NT_STATUS_V(x) ((x).v) +#else +typedef uint32_t NTSTATUS; +#define NT_STATUS(x) (x) +#define NT_STATUS_V(x) (x) +#endif + +#define NT_STATUS_OK NT_STATUS(0x0000) +#define NT_STATUS_ACCESS_DENIED NT_STATUS(0xC0000000 | 0x0022) +#define NT_STATUS_LOGON_FAILURE NT_STATUS(0xC0000000 | 0x006d) +#endif + +typedef struct smb_file_s { + int fnum; + int offset; + int whence; + char *fname; +}smb_file_t; + + +#ifdef __cplusplus +extern "C" { +#endif +struct cli_state *smbc_cli_initialize(); +uint32_t smbc_cli_connect(struct cli_state *cli, const char *desthost, int port); +void smbc_cli_shutdown(struct cli_state *cli); +int smbc_cli_get_smb_secblob(struct cli_state *cli, unsigned char *blob); +uint32_t smbc_cli_get_smb_challenge(struct cli_state *cli, char *blob); +uint32_t smbc_cli_send_negprot(struct cli_state *cli); +uint32_t smbc_cli_send_negprot_done(struct cli_state *cli); +int smbc_cli_get_protocol(struct cli_state *cli); +int smbc_cli_get_socket(struct cli_state *cli); +uint32_t smbc_cli_get_capabilities(struct cli_state *cli); +uint32_t smbc_cli_tree_connect(struct cli_state *cli, char *fname); +int smbc_cli_parse_path(const char *fname, + char *pWorkgroup, + char *pServer, + char *pShare, + char *pPath); +int smbc_cli_stat(struct cli_state *cli, const char *fname, struct stat *st); +SMBCFILE *smbc_cli_opendir2(const char *fname); +SMBCFILE *smbc_cli_opendir(struct cli_state *cli, const char *fname); +SMBCFILE *smbc_cli_open_share(struct cli_state *cli, const char *fname); +uint32_t smbc_cli_rmdir(struct cli_state *cli, const char *dname); +uint32_t smbc_cli_mkdir(struct cli_state *cli, const char *fname); +uint32_t smbc_cli_rename(struct cli_state *cli, char *src, char *dst); +struct smbc_dirent *smbc_cli_readdir(SMBCFILE *dir); +int smbc_cli_closedir(SMBCFILE *dir); +int smbc_cli_list(struct cli_state *cli,const char *mask, unsigned short attribute, + void (*fn)(const char *, file_info *, const char *, void *), void *state); +void* smbc_cli_ntlmssp_state_alloc(); +void smbc_cli_ntlmssp_state_free(void *state); +int smbc_cli_send_session_setup_nego(struct cli_state *cli, void *state, char *ntlm_msg, int ntlm_len); +uint32_t smbc_cli_session_setup_ntlmssp_nego(struct cli_state *cli, void *state, char *ntlm_msg, int ntlm_msg_len); +uint32_t smbc_cli_session_setup_ntlmssp_auth(struct cli_state *cli, void *state, char *ntlm_msg, int ntlm_msg_len); +uint32_t smbc_cli_session_setup_lanman2(struct cli_state *cli, char *ntlm_msg, int ntlm_msg_len); +smb_file_t *smbc_cli_ntcreate(struct cli_state *cli, char *fname, + uint32_t desired_access, + uint32_t create_disposition, + uint32_t create_options); + +uint32_t smbc_cli_get(struct cli_state *cli, char *pathname, + NTSTATUS (*sink)(char *buf, size_t n, void *priv), + void *priv); +uint32_t smbc_cli_put(struct cli_state *cli, char *rname, int reput, + size_t (*push_source)(uint8_t *buf, size_t n, void *priv), + void *priv); +smb_file_t* smbc_cli_open(struct cli_state *cli, char *rname, int flags); +uint32_t smbc_cli_lseek(struct cli_state *cli, smb_file_t *smbf, off_t offset, int whence); +size_t smbc_cli_write(struct cli_state *cli, smb_file_t *smbf, uint16_t write_mode, const char *buf, size_t size); +size_t smbc_cli_read(struct cli_state *cli, smb_file_t *smbf, char *buf, size_t size); +uint32_t smbc_cli_close(struct cli_state *cli, smb_file_t *smbf); +uint32_t smbc_cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs); +void *smbc_cli_nmb_lookup( void *priv ); +void smbc_cli_nmb_terminate(int term); + +//- Jerry add +const char* smbc_nmblookup(const char* ip); +#ifdef __cplusplus +} +#endif + + +#endif //#if 0 + +#endif /* SMBCLIENT_H_INCLUDED */ diff --git a/release/src-rt/include/linux_gpio.h b/release/src-rt/include/linux_gpio.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/linux_osl.h b/release/src-rt/include/linux_osl.h old mode 100644 new mode 100755 index f3d887ecff..3475f98ed5 --- a/release/src-rt/include/linux_osl.h +++ b/release/src-rt/include/linux_osl.h @@ -163,8 +163,6 @@ extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); #define DMA_RX 2 /* RX direction for DMA */ /* map/unmap shared (dma-able) memory */ -#define DMA_MAP(osh, va, size, direction, p, dmah) \ - osl_dma_map((osh), (va), (size), (direction)) #define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ osl_dma_unmap((osh), (pa), (size), (direction)) extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); @@ -207,10 +205,7 @@ extern int osl_error(int bcmerror); #include /* for mem*, str* */ #define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) - -#ifndef printf #define printf(fmt, args...) printk(fmt , ## args) -#endif /* bcopy's: Linux kernel doesn't provide these (anymore) */ #define bcopy(src, dst, len) memcpy((dst), (src), (len)) @@ -430,13 +425,13 @@ typedef struct ctfpool { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) #define FASTBUF (1 << 4) #define CTFBUF (1 << 5) -#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) |= FASTBUF) -#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) &= (~FASTBUF)) -#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) |= CTFBUF) -#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) &= (~CTFBUF)) -#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) & FASTBUF) -#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->ctf_mac_len) & CTFBUF) -#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->ctf_mac_len) +#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) +#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) +#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) +#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) +#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) +#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) +#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) #else #define FASTBUF (1 << 0) #define CTFBUF (1 << 1) @@ -459,12 +454,37 @@ extern void osl_ctfpool_cleanup(osl_t *osh); extern void osl_ctfpool_stats(osl_t *osh, void *b); #endif /* CTFPOOL */ +#ifdef CTFMAP +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) +#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->sp) +#else /* 2.6.14 */ +#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->list) +#endif /* 2.6.14 */ + +#define PKTCTFMAP(osh, p) \ +do { \ + if (PKTISCTF(osh, p)) { \ + int32 sz; \ + sz = (uint32)(((struct sk_buff *)p)->tail) - \ + (uint32)CTFMAPPTR(osh, p); \ + /* map the remaining unmapped area */ \ + if (sz > 0) { \ + _DMA_MAP(osh, (void *)CTFMAPPTR(osh, p), \ + sz, DMA_RX, p, NULL); \ + } \ + /* clear ctf buf flag */ \ + PKTCLRCTF(osh, p); \ + CTFMAPPTR(osh, p) = NULL; \ + } \ +} while (0) +#endif /* CTFMAP */ + #ifdef HNDCTF #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) #define SKIPCT (1 << 6) -#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->ctf_mac_len |= SKIPCT) -#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->ctf_mac_len &= (~SKIPCT)) -#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->ctf_mac_len & SKIPCT) +#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) +#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) +#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) #else /* 2.6.22 */ #define SKIPCT (1 << 2) #define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) @@ -793,6 +813,25 @@ extern void osl_pktlist_remove(osl_t *osh, void *p); #endif /* BINOSL */ +#ifdef CTFMAP +#include +#define CTFMAPSZ 320 +#define DMA_MAP(osh, va, size, direction, p, dmah) \ +({ \ + typeof(size) sz = (size); \ + if (PKTISCTF((osh), (p))) { \ + sz = CTFMAPSZ; \ + CTFMAPPTR((osh), (p)) = (void *)(((uint8 *)(va)) + CTFMAPSZ); \ + } \ + osl_dma_map((osh), (va), sz, (direction)); \ +}) +#define _DMA_MAP(osh, va, size, direction, p, dmah) \ + dma_cache_inv((uint)(va), (size)) +#else /* CTFMAP */ +#define DMA_MAP(osh, va, size, direction, p, dmah) \ + osl_dma_map((osh), (va), (size), (direction)) +#endif /* CTFMAP */ + #else /* ! BCMDRIVER */ diff --git a/release/src-rt/include/linuxver.h b/release/src-rt/include/linuxver.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/min_osl.h b/release/src-rt/include/min_osl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/miniopt.h b/release/src-rt/include/miniopt.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/mips33_core.h b/release/src-rt/include/mips33_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/mips74k_core.h b/release/src-rt/include/mips74k_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/mipsinc.h b/release/src-rt/include/mipsinc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/ndiserrmap.h b/release/src-rt/include/ndiserrmap.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/nflash.h b/release/src-rt/include/nflash.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/nicpci.h b/release/src-rt/include/nicpci.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/oidencap.h b/release/src-rt/include/oidencap.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/osl.h b/release/src-rt/include/osl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/packed_section_end.h b/release/src-rt/include/packed_section_end.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/packed_section_start.h b/release/src-rt/include/packed_section_start.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/pci_core.h b/release/src-rt/include/pci_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/pcicfg.h b/release/src-rt/include/pcicfg.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/pcie_core.h b/release/src-rt/include/pcie_core.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/proto/202.3.h b/release/src-rt/include/proto/802.3.h old mode 100644 new mode 100755 similarity index 100% rename from release/src-rt/include/proto/202.3.h rename to release/src-rt/include/proto/802.3.h diff --git a/release/src-rt/include/proto/bcmip.h b/release/src-rt/include/proto/bcmip.h old mode 100644 new mode 100755 index 6ebbcacf52..2da19c52b6 --- a/release/src-rt/include/proto/bcmip.h +++ b/release/src-rt/include/proto/bcmip.h @@ -42,6 +42,7 @@ #define IP_PROT_ICMP 0x1 /* ICMP protocol */ #define IP_PROT_TCP 0x6 /* TCP protocol */ #define IP_PROT_UDP 0x11 /* UDP protocol type */ +#define IP_PROT_IGMP 0x02 /* IGMP protocol */ /* IPV4 field offsets */ #define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ diff --git a/release/src-rt/include/proto/papol.h b/release/src-rt/include/proto/eapol.h old mode 100644 new mode 100755 similarity index 100% rename from release/src-rt/include/proto/papol.h rename to release/src-rt/include/proto/eapol.h diff --git a/release/src-rt/include/proto/mcmip.h b/release/src-rt/include/proto/mcmip.h deleted file mode 100644 index 2da19c52b6..0000000000 --- a/release/src-rt/include/proto/mcmip.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Fundamental constants relating to IP Protocol - * - * $Id: bcmip.h,v 9.19 2009-11-10 20:08:33 Exp $ - */ - -#ifndef _bcmip_h_ -#define _bcmip_h_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - -/* This marks the start of a packed structure section. */ -#include - - -/* IPV4 and IPV6 common */ -#define IP_VER_OFFSET 0x0 /* offset to version field */ -#define IP_VER_MASK 0xf0 /* version mask */ -#define IP_VER_SHIFT 4 /* version shift */ -#define IP_VER_4 4 /* version number for IPV4 */ -#define IP_VER_6 6 /* version number for IPV6 */ - -#define IP_VER(ip_body) \ - ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) - -#define IP_PROT_ICMP 0x1 /* ICMP protocol */ -#define IP_PROT_TCP 0x6 /* TCP protocol */ -#define IP_PROT_UDP 0x11 /* UDP protocol type */ -#define IP_PROT_IGMP 0x02 /* IGMP protocol */ - -/* IPV4 field offsets */ -#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ -#define IPV4_TOS_OFFSET 1 /* type of service offset */ -#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ -#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ -#define IPV4_PROT_OFFSET 9 /* protocol type offset */ -#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ -#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ -#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ -#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ - -/* IPV4 field decodes */ -#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ -#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ - -#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ -#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) - -#define IPV4_ADDR_LEN 4 /* IPV4 address length */ - -#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ - ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) - -#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ - ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) - -#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ -#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ - -#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) - -#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ -#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ - -#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ -#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ -#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ - -#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) - -#define IPV4_FRAG_RESV 0x8000 /* Reserved */ -#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ -#define IPV4_FRAG_MORE 0x2000 /* More fragments */ -#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ - -#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ - -/* IPV4 packet formats */ -BWL_PRE_PACKED_STRUCT struct ipv4_addr { - uint8 addr[IPV4_ADDR_LEN]; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct ipv4_hdr { - uint8 version_ihl; /* Version and Internet Header Length */ - uint8 tos; /* Type Of Service */ - uint16 tot_len; /* Number of bytes in packet (max 65535) */ - uint16 id; - uint16 frag; /* 3 flag bits and fragment offset */ - uint8 ttl; /* Time To Live */ - uint8 prot; /* Protocol */ - uint16 hdr_chksum; /* IP header checksum */ - uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ - uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ -} BWL_POST_PACKED_STRUCT; - -/* IPV6 field offsets */ -#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ -#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ -#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ -#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ -#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ - -/* IPV6 field decodes */ -#define IPV6_TRAFFIC_CLASS(ipv6_body) \ - (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ - ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) - -#define IPV6_FLOW_LABEL(ipv6_body) \ - (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ - (((uint8 *)(ipv6_body))[2] << 8) | \ - (((uint8 *)(ipv6_body))[3])) - -#define IPV6_PAYLOAD_LEN(ipv6_body) \ - ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ - ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) - -#define IPV6_NEXT_HDR(ipv6_body) \ - (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) - -#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) - -#define IPV6_ADDR_LEN 16 /* IPV6 address length */ - -/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ -#define IP_TOS46(ip_body) \ - (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ - IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) - -/* This marks the end of a packed structure section. */ -#include - -#endif /* _bcmip_h_ */ diff --git a/release/src-rt/include/qmath.h b/release/src-rt/include/qmath.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbchipc.h b/release/src-rt/include/sbchipc.h old mode 100644 new mode 100755 index dff21be65c..c05880582c --- a/release/src-rt/include/sbchipc.h +++ b/release/src-rt/include/sbchipc.h @@ -1213,10 +1213,10 @@ typedef volatile struct { /* 4706 PMU */ #define PMU4706_MAINPLL_PLL0 0 #define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ -#define PMU6_4706_PROC_P1DIV_MASK 0x000f0000 -#define PMU6_4706_PROC_P1DIV_SHIFT 16 -#define PMU6_4706_PROC_P2DIV_MASK 0x0000f000 -#define PMU6_4706_PROC_P2DIV_SHIFT 12 +#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 +#define PMU6_4706_PROC_P2DIV_SHIFT 16 +#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 +#define PMU6_4706_PROC_P1DIV_SHIFT 12 #define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 #define PMU6_4706_PROC_NDIV_INT_SHIFT 3 #define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 diff --git a/release/src-rt/include/sbconfig.h b/release/src-rt/include/sbconfig.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbgige.h b/release/src-rt/include/sbgige.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbhndcpu.h b/release/src-rt/include/sbhndcpu.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbhnddma.h b/release/src-rt/include/sbhnddma.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbhndpio.h b/release/src-rt/include/sbhndpio.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbmemc.h b/release/src-rt/include/sbmemc.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbpcmcia.h b/release/src-rt/include/sbpcmcia.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbsdio.h b/release/src-rt/include/sbsdio.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbsdpcmdev.h b/release/src-rt/include/sbsdpcmdev.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbsdram.h b/release/src-rt/include/sbsdram.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbsocram.h b/release/src-rt/include/sbsocram.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbsprom.h b/release/src-rt/include/sbsprom.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sbusbd.h b/release/src-rt/include/sbusbd.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/sflash.h b/release/src-rt/include/sflash.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/siutils.h b/release/src-rt/include/siutils.h old mode 100644 new mode 100755 index b6d15df8d9..c0769a767f --- a/release/src-rt/include/siutils.h +++ b/release/src-rt/include/siutils.h @@ -174,6 +174,7 @@ extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); extern int si_numaddrspaces(si_t *sih); extern uint32 si_addrspace(si_t *sih, uint asidx); extern uint32 si_addrspacesize(si_t *sih, uint asidx); +extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); extern int si_corebist(si_t *sih); extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); extern void si_core_disable(si_t *sih, uint32 bits); diff --git a/release/src-rt/include/trxhdr.h b/release/src-rt/include/trxhdr.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/typedefs.h b/release/src-rt/include/typedefs.h old mode 100644 new mode 100755 index d64125a6d8..fb3152eab0 --- a/release/src-rt/include/typedefs.h +++ b/release/src-rt/include/typedefs.h @@ -120,11 +120,17 @@ typedef unsigned __int64 uint64; #endif #endif /* KERNEL */ #define TYPEDEF_BOOL -#endif +#endif /* MAXOSX */ #if defined(__NetBSD__) -#define TYPEDEF_ULONG +#ifndef _KERNEL +#include #endif +#define TYPEDEF_BOOL +#define TYPEDEF_UINT +#define TYPEDEF_USHORT +#define TYPEDEF_ULONG +#endif /* NetBSD */ #if defined(__sparc__) #define TYPEDEF_ULONG diff --git a/release/src-rt/include/usbrdl.h b/release/src-rt/include/usbrdl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/usbstd.h b/release/src-rt/include/usbstd.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/wlc_extlog_idstr.h b/release/src-rt/include/wlc_extlog_idstr.h old mode 100644 new mode 100755 diff --git a/release/src-rt/include/wlioctl.h b/release/src-rt/include/wlioctl.h old mode 100644 new mode 100755 index 20a58555b8..a37b7deb95 --- a/release/src-rt/include/wlioctl.h +++ b/release/src-rt/include/wlioctl.h @@ -1576,11 +1576,11 @@ typedef struct wl_po { #define WL_CHAN_FREQ_RANGE_5GM 2 #define WL_CHAN_FREQ_RANGE_5GH 3 -#define WL_CHAN_FREQ_RANGE_5GLL_VER2 4 -#define WL_CHAN_FREQ_RANGE_5GLH_VER2 5 -#define WL_CHAN_FREQ_RANGE_5GML_VER2 6 -#define WL_CHAN_FREQ_RANGE_5GMH_VER2 7 -#define WL_CHAN_FREQ_RANGE_5GH_VER2 8 +#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 +#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 +#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 +#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 +#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 /* phy types (returned by WLC_GET_PHYTPE) */ #define WLC_PHY_TYPE_A 0 @@ -1673,6 +1673,9 @@ typedef struct wl_po { #define WLC_N_SGI_20 0x01 #define WLC_N_SGI_40 0x02 +/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ +#define WLC_SGI_ALL 0x02 + /* Values for PM */ #define PM_OFF 0 #define PM_MAX 1 @@ -3354,6 +3357,7 @@ typedef enum { #define VNDR_IE_AUTHRSP_FLAG 0x8 #define VNDR_IE_PRBREQ_FLAG 0x10 #define VNDR_IE_ASSOCREQ_FLAG 0x20 +#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ #define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ #define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) @@ -3373,6 +3377,28 @@ typedef BWL_PRE_PACKED_STRUCT struct { vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ } BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; +typedef BWL_PRE_PACKED_STRUCT struct { + uint8 id; /* IE type */ + uint8 len; /* IE length */ + uint8 data[1]; /* IE data */ +} BWL_POST_PACKED_STRUCT ie_info_t; + +typedef BWL_PRE_PACKED_STRUCT struct { + int iecount; /* number of entries in the ie_list[] array */ + uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ + ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ +} BWL_POST_PACKED_STRUCT ie_buf_t; + +typedef BWL_PRE_PACKED_STRUCT struct { + char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ + ie_buf_t ie_buffer; /* buffer containing IE list information */ +} BWL_POST_PACKED_STRUCT ie_setbuf_t; + +typedef BWL_PRE_PACKED_STRUCT struct { + uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ + uint8 id; /* IE type */ +} BWL_POST_PACKED_STRUCT ie_getbuf_t; + /* structures used to define format of wps ie data from probe requests */ /* passed up to applications via iovar "prbreq_wpsie" */ typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { diff --git a/release/src-rt/include/wllmacctl.h b/release/src-rt/include/wllmacctl.h old mode 100644 new mode 100755 diff --git a/release/src-rt/shared/aisdram.S b/release/src-rt/shared/aisdram.S old mode 100644 new mode 100755 index a0df4e5b5b..6171dc0178 --- a/release/src-rt/shared/aisdram.S +++ b/release/src-rt/shared/aisdram.S @@ -25,6 +25,7 @@ #include #include #include +#include #include #if defined(NFLASH_SUPPORT) @@ -51,7 +52,7 @@ li k0,KSEG1ADDR(0x18000040); \ li k1,x; \ sw k1,FLADDR_OFF(k0) - + #define TRACE(x) \ li k1,x; \ sw k1,FLADDR_OFF(k0) @@ -193,7 +194,7 @@ ddr2_init: nfl_pagesz_map: /* page size mapping */ .word 0x200, 0x800, 0x1000, 0x2000 - + nfl_blksz_map: /* block size mapping */ .word 0x4000, 0x20000, 0x2000, 0x80000, 0x40000, 0, 0, 0 @@ -261,7 +262,7 @@ LEAF(ai_draminit) beq s4,DMEMS_CORE_ID,founddmemc nop - beq s4,AMEMC_CORE_ID,foundamemc + beq s4,AMEMC_CORE_ID,founddmemc nop b 1b @@ -272,17 +273,6 @@ noctrl: TRACE(0x415307) jr t6 li v0,-1 -foundamemc: - beqz s5,1f # Running from RAM, simply return - nop - - la t2,ai_amemcinit - add t2,t2,s5 - jalr t2 - nop -1: - jr t6 - move v0,zero founddmemc: TRACE(0x415308) @@ -292,10 +282,10 @@ founddmemc: */ bnez s5,1f # Not running from RAM, go ahead nop - + jr t6 # Return with 0 rc. move v0,zero - + /* We'll cheat a little: memory controllers don't have master ports, so * the EROM entry right after the CIDs is the slave port for the registers */ @@ -355,6 +345,11 @@ swrap: and a2,t0,t2 srl s3,t3,CIB_REV_SHIFT # s3 = core revision beq s4,DMEMS_CORE_ID,1f nop + + /* Go find nvram if the controller is AMEMC. */ + beq s4,AMEMC_CORE_ID,find_nvram + nop + ble s3,1,is16x nop @@ -379,7 +374,7 @@ is16x: TRACE(0x41530b) find_nvram: TRACE(0x41530c) li t0,KSEG1ADDR(SI_FLASH2 - NVRAM_SPACE) - li t1,FLASH_MIN + li t1,FLASH_MIN li t2,SI_FLASH2_SZ li t3,NVRAM_MAGIC @@ -390,7 +385,7 @@ find_nvram: bne t4,BCM5357_CHIP_ID,1f nop lw t5,CC_CHIPST(s2) - li t4,0x10 + li t4,0x10 and t4,t4,t5 beqz t4,1f nop @@ -482,7 +477,7 @@ embedded_nv: b init_dmemc li s0,0x144 - + read_config: /* sdram_config is a 16bit value 12 bytes inside the nvram hdr. * Currently it is defined as: @@ -504,8 +499,20 @@ read_config: */ TRACE(0x415310) lw s0,12(t4) # Pick up sdram_config & sdram_refresh + + /* Determine if it is DMEMC or AMEMC */ + bne s4,AMEMC_CORE_ID,init_dmemc lw s8,16(t4) # Pick up sdram_ncdl + /* Initailize AMEMC */ + la t2,ai_amemcinit + add t2,t2,s5 + jalr t2 + nop + + jr t6 + move v0,zero + /* Initialize DMEMC/DMEMS */ init_dmemc: /* For DDR2, init pvt controller */ @@ -605,7 +612,7 @@ nvover: beqz s8,chhalf and t1,t1,t2 or t0,t0,t1 sw t0,DMEMC_CONTROL141(a1) - + li t0,0x7f0000 and t0,t0,s0 # clk_wr_delay_0 srl t0,t0,8 @@ -636,7 +643,7 @@ old_ncdl: sw t0,DMEMC_CONTROL23(a1) sw s8,DMEMC_CONTROL22(a1) - + /* Check for half-width */ chhalf: li t0,0x80 and t0,t0,s0 @@ -659,7 +666,7 @@ ch8banks: nop /* Change regs for 8-bank DDRs */ -do8banks: +do8banks: lw t0,DMEMC_CONTROL05(a1) li t1,0x00010000 or t0,t0,t1 @@ -761,17 +768,17 @@ dobypass: bgt s3,1,4f nop - + 1: li t0,0x00170017 beq a3,DM_STAT_SDR,2f nop - + li t0,0x000f000f beq a3,DM_STAT_DDR1,2f nop li t0,0x00200020 - + 2: sw t0,DMEMC_CONTROL25(a1) beq s4,DMEMS_CORE_ID,3f nop @@ -799,7 +806,7 @@ dobypass: ble s3,1,ckvsim nop - + lw t0,DMEMC_CONTROL140(a1) li t1,0x10000000 or t0,t0,t1 @@ -848,7 +855,7 @@ turnon: sll t0,t1,16 or t2,t2,t0 sw t2,DMEMC_CONTROL140(a1) - + lw t2,DMEMC_CONTROL142(a1) li t0,~0x01ff8000 and t2,t2,t0 @@ -859,7 +866,7 @@ turnon: sll t0,t0,15 or t2,t2,t0 sw t2,DMEMC_CONTROL142(a1) - + lw t1,DMEMC_CONTROL145(a1) srl t1,t1,3 lw t2,DMEMC_CONTROL141(a1) @@ -868,7 +875,7 @@ turnon: sll t0,t1,16 or t2,t2,t0 sw t2,DMEMC_CONTROL141(a1) - + lw t2,DMEMC_CONTROL143(a1) li t0,~0x01ff8000 and t2,t2,t0 @@ -947,12 +954,12 @@ ai_core_reset: dmemc_init_regs: beq s4,DMEMS_CORE_ID,loop_regs li t3,128 - + ble s3,1,loop_regs nop li t3,256 - + loop_regs: add a0,a0,s5 # Relocate address li t0,DMEMC_TABLE_END @@ -988,7 +995,7 @@ LEAF(nfl_size_block) add a0,a0,s5 # Relocate address add t8,t8,a0 lw v1,0(t8) - + li t8,0x7 sll t8,28 and t8,t8,t9 @@ -1046,169 +1053,37 @@ END(nfl_check_badb) /* ********************************************************************* * AI_AMEMCINIT - * + * * AI version of DDR / memory controller initialization * * This routine deals with DDR23_PHY and PL341 MEMC. - * + * ********************************************************************* */ -#define MEMC_BURST_LENGTH (4) /* Convenient macro for writing registers (use t0 for base) */ #define ddr_write(offset, value) \ li a0, (value); \ sw a0, offset(t0); -#define AI_DDRPHY_BASE (0x1800f000) -#define AI_MEMC_BASE (0x18006000) -#define AI_MEMC_SLAVE_BASE (0x18106000) - -/* From bsp_config.h of _BCM953003RSP_ */ -/* (required) PLL clock */ -#define CFG_DDR_PLL_CLOCK (331250) /* KHz */ - -/* (required) Row bits: 0=11bits, 1=12bits, ..., 5=16bits */ -#define CFG_DDR_ROW_BITS 2 /* 13 bits */ - -/* (required) Column bits: 1=9bits, 2=10bits, 3=11bits */ -#define CFG_DDR_COLUMN_BITS 2 /* 10 bits */ - -/* (required) Bank bits: 0=2bits, 3=3bits */ -#define CFG_DDR_BANK_BITS 3 - -/* (required) Memory width: 0=16bits, 1=32bits, 2=64bits */ -#define CFG_DDR_MEM_WIDTH 1 - -/* (required) CAS Latency (NOTE: could be affected by PLL clock) */ -#define CFG_DDR_CAS_LATENCY 5 - -/* (required) t_wr (picoseconds) */ -#define CFG_DDR_T_WR 15000 - -/* (optional) Refresh period t_refi (picoseconds) */ -#define CFG_DDR_REFRESH_PRD 7800000 - -/* (optional) t_rfc (picoseconds) */ -#define CFG_DDR_T_RFC 105000 - -/* - * Convenient macros - */ -#define MEMCYCLES(psec) (((psec) * (CFG_DDR_PLL_CLOCK) + 999999999) / 1000000000) - -/* - * Convenient macros (minimum requirement and truncated decimal) - */ -#define MEMCYCLES_MIN(psec) ((psec) * (CFG_DDR_PLL_CLOCK) / 1000000000) - -/* - * PLL clock configuration - */ -#define PLL_NDIV_INT_VAL (16 * (CFG_DDR_PLL_CLOCK) / 100000) - -/* - * DDR23PHY registers - */ -#define DDR23PHY_PLL_STATUS 0x010 -#define DDR23PHY_PLL_CONFIG 0x014 -#define DDR23PHY_PLL_PRE_DIVIDER 0x018 -#define DDR23PHY_PLL_DIVIDER 0x01c -#define DDR23PHY_STATIC_VDL_OVERRIDE 0x030 -#define DDR23PHY_ZQ_PVT_COMP_CTL 0x03c -#define DDR23PHY_BL3_VDL_CALIBRATE 0x104 -#define DDR23PHY_BL3_VDL_STATUS 0x108 -#define DDR23PHY_BL3_READ_CONTROL 0x130 -#define DDR23PHY_BL3_WR_PREAMBLE_MODE 0x148 -#define DDR23PHY_BL2_VDL_CALIBRATE 0x204 -#define DDR23PHY_BL2_VDL_STATUS 0x208 -#define DDR23PHY_BL2_READ_CONTROL 0x230 -#define DDR23PHY_BL2_WR_PREAMBLE_MODE 0x248 -#define DDR23PHY_BL1_VDL_CALIBRATE 0x304 -#define DDR23PHY_BL1_VDL_STATUS 0x308 -#define DDR23PHY_BL1_READ_CONTROL 0x330 -#define DDR23PHY_BL1_WR_PREAMBLE_MODE 0x348 -#define DDR23PHY_BL0_VDL_CALIBRATE 0x404 -#define DDR23PHY_BL0_VDL_STATUS 0x408 -#define DDR23PHY_BL0_READ_CONTROL 0x430 -#define DDR23PHY_BL0_WR_PREAMBLE_MODE 0x448 - -/* - * PL341 registers - */ -#define PL341_memc_status 0x000 -#define PL341_memc_cmd 0x004 -#define PL341_direct_cmd 0x008 -#define PL341_memory_cfg 0x00c -#define PL341_refresh_prd 0x010 -#define PL341_cas_latency 0x014 -#define PL341_write_latency 0x018 -#define PL341_t_mrd 0x01c -#define PL341_t_ras 0x020 -#define PL341_t_rc 0x024 -#define PL341_t_rcd 0x028 -#define PL341_t_rfc 0x02c -#define PL341_t_rp 0x030 -#define PL341_t_rrd 0x034 -#define PL341_t_wr 0x038 -#define PL341_t_wtr 0x03c -#define PL341_t_xp 0x040 -#define PL341_t_xsr 0x044 -#define PL341_t_esr 0x048 -#define PL341_memory_cfg2 0x04c -#define PL341_memory_cfg3 0x050 -#define PL341_t_faw 0x054 -#define PL341_chip_0_cfg 0x200 -#define PL341_user_config0 0x304 - - -/* - * Values for PL341 Direct Command Register - */ -#define MCHIP_CMD_PRECHARGE_ALL (0x0 << 18) -#define MCHIP_CMD_AUTO_REFRESH (0x1 << 18) -#define MCHIP_CMD_MODE_REG (0x2 << 18) -#define MCHIP_CMD_NOP (0x3 << 18) -#define MCHIP_MODEREG_SEL(x) ((x) << 16) -#define MCHIP_MR_WRITE_RECOVERY(x) (((x) - 1) << 9) -#define MCHIP_MR_DLL_RESET(x) ((x) << 8) -#define MCHIP_MR_CAS_LATENCY(x) ((x) << 4) -#if MEMC_BURST_LENGTH == 4 -#define MCHIP_MR_BURST_LENGTH (2) -#else -#define MCHIP_MR_BURST_LENGTH (3) -#endif -#define MCHIP_EMR1_DLL_DISABLE(x) ((x) << 0) -#define MCHIP_EMR1_RTT_ODT_DISABLED (0) -#define MCHIP_EMR1_RTT_75_OHM (1 << 2) -#define MCHIP_EMR1_RTT_150_OHM (1 << 6) -#define MCHIP_EMR1_RTT_50_OHM ((1 << 6) | (1 << 2)) -#define MCHIP_EMR1_OCD_CALI_EXIT (0x0 << 7) -#define MCHIP_EMR1_OCD_CALI_DEFAULT (0x3 << 7) - LEAF(ai_amemcinit) .set noreorder - - move t7,ra - - /* + + /* * ddr23_phy_init */ li t0, KSEG1ADDR(AI_DDRPHY_BASE) - #ifndef CFG_QUICKTURN -#define PVT_MAX_RETRY (120) -#define PVT_MATCHED_COUNT (3) li t2, 0x10000000 li t3, 0 li t5, 0 2: /* Do recalibration */ beq t5, PVT_MAX_RETRY, 9f - lw a1, DDR23PHY_ZQ_PVT_COMP_CTL(t0) + lw t7, DDR23PHY_ZQ_PVT_COMP_CTL(t0) ddr_write(DDR23PHY_ZQ_PVT_COMP_CTL, 0x04000000); -1: +1: /* Wait until sample_done == 1 */ lw t1, DDR23PHY_ZQ_PVT_COMP_CTL(t0) and t1, t1, t2; @@ -1217,12 +1092,12 @@ LEAF(ai_amemcinit) /* Increase total retry count */ add t5, t5, 1 - + /* Check if the result is the same as previous one */ lw t1, DDR23PHY_ZQ_PVT_COMP_CTL(t0) - beq t1, a1, 3f + beq t1, t7, 3f nop - + /* If not, clear matched count */ b 2b li t3, 0 @@ -1232,14 +1107,14 @@ LEAF(ai_amemcinit) bne t3, PVT_MATCHED_COUNT, 2b nop 9: - + /* setup PLL */ ddr_write(DDR23PHY_PLL_CONFIG, 0x8000000c); - ddr_write(DDR23PHY_PLL_PRE_DIVIDER, + ddr_write(DDR23PHY_PLL_PRE_DIVIDER, 0x00000011 + (PLL_NDIV_INT_VAL << 8)); ddr_write(DDR23PHY_PLL_DIVIDER, 0x02000000); ddr_write(DDR23PHY_PLL_CONFIG, 0x80000008); - + /* Wait for PLL locked */ li t2, 1; 1: /* Wait until lock == 1 */ @@ -1252,16 +1127,16 @@ LEAF(ai_amemcinit) ddr_write(DDR23PHY_PLL_CONFIG, 0x80000000); ddr_write(DDR23PHY_PLL_CONFIG, 0x00000000); - /* + /* * Calibrate VDL */ - + /* calib_once + calib_fast (for all BL) */ ddr_write(DDR23PHY_BL3_VDL_CALIBRATE, 0x00000003); ddr_write(DDR23PHY_BL2_VDL_CALIBRATE, 0x00000003); ddr_write(DDR23PHY_BL1_VDL_CALIBRATE, 0x00000003); ddr_write(DDR23PHY_BL0_VDL_CALIBRATE, 0x00000003); - + li t2, 0x0000003; li t0, KSEG1ADDR(AI_DDRPHY_BASE) 1: /* Wait until calib_idle == 1 and locked for all BL */ @@ -1281,7 +1156,7 @@ LEAF(ai_amemcinit) and t1, t1, t2; beq t1, zero, 1b nop - + /* VDL override */ lw t1, DDR23PHY_BL0_VDL_STATUS(t0) srl t1, t1, 8 @@ -1293,203 +1168,244 @@ LEAF(ai_amemcinit) sll t1, 20 or t2, t2, t1 /* ovr_force */ sw t2, DDR23PHY_STATIC_VDL_OVERRIDE(t0) - + #endif /* !CFG_QUICKTURN */ /* * Memory controller PL341 initialization - */ - + */ + /* De-assert core reset */ - li t0, KSEG1ADDR(AI_MEMC_SLAVE_BASE); + move t0, a2 # AMEMC DMP regs ddr_write(AI_RESETCTRL, 0x00000000) - - li t0, KSEG1ADDR(AI_MEMC_BASE); - + + move t0, a1 # AMEMC regs + #ifdef CFG_DDR_REFRESH_PRD /* refresh_prd */ ddr_write(PL341_refresh_prd, MEMCYCLES_MIN(CFG_DDR_REFRESH_PRD)); #endif - -#ifdef CFG_DDR_CAS_LATENCY - /* cas_latency */ - ddr_write(PL341_cas_latency, (CFG_DDR_CAS_LATENCY << 1)); -#endif - -#ifdef CFG_DDR_WRITE_LATENCY - /* write_latency */ - ddr_write(PL341_write_latency, CFG_DDR_WRITE_LATENCY); -#endif - + #ifdef CFG_DDR_T_MRD /* MRD time [6:0] */ ddr_write(PL341_t_mrd, MEMCYCLES(CFG_DDR_T_MRD)); #endif - + #ifdef CFG_DDR_T_RAS /* ras time [4:0] */ ddr_write(PL341_t_ras, MEMCYCLES(CFG_DDR_T_RAS)); #endif - + #ifdef CFG_DDR_T_RC /* t_rc [4:0] */ ddr_write(PL341_t_rc, MEMCYCLES(CFG_DDR_T_RC)); #endif - + #ifdef CFG_DDR_T_RCD /* t_rcd [4:0] */ ddr_write(PL341_t_rcd, MEMCYCLES(CFG_DDR_T_RCD)); #endif - + #ifdef CFG_DDR_T_RFC /* t_rfc [6:0] schedule_rfc[14:8] */ ddr_write(PL341_t_rfc, ((MEMCYCLES(CFG_DDR_T_RFC) - 3) << 8) | MEMCYCLES(CFG_DDR_T_RFC)); #endif - + #ifdef CFG_DDR_T_RP /* t_rp [3:0] */ - ddr_write(PL341_t_rp, + ddr_write(PL341_t_rp, ((MEMCYCLES(CFG_DDR_T_RP) - 3) << 8) | MEMCYCLES(CFG_DDR_T_RP)); #endif - + #ifdef CFG_DDR_T_RRD /* t_rrd [2:0] */ ddr_write(PL341_t_rrd, MEMCYCLES(CFG_DDR_T_RRD)); #endif - + #ifdef CFG_DDR_T_WR /* t_wr */ ddr_write(PL341_t_wr, MEMCYCLES(CFG_DDR_T_WR)); #endif - + #ifdef CFG_DDR_T_WTR /* t_wtr */ ddr_write(PL341_t_wtr, MEMCYCLES(CFG_DDR_T_WTR)); #endif - + #ifdef CFG_DDR_T_XP /* t_xp[7:0] */ ddr_write(PL341_t_xp, MEMCYCLES(CFG_DDR_T_XP)); #endif - + #ifdef CFG_DDR_T_XSR /* t_xsr[7:0] */ ddr_write(PL341_t_xsr, MEMCYCLES(CFG_DDR_T_XSR)); #endif - + #ifdef CFG_DDR_T_ESR /* t_esr[7:0] */ ddr_write(PL341_t_esr, MEMCYCLES(CFG_DDR_T_ESR)); #endif - + #ifdef CFG_DDR_T_FAW /* t_faw */ - ddr_write(PL341_t_faw, + ddr_write(PL341_t_faw, ((MEMCYCLES(CFG_DDR_T_FAW) - 3) << 8) | MEMCYCLES(CFG_DDR_T_FAW)); #endif - - /* memory_cfg register */ - ddr_write(PL341_memory_cfg, - (2 << 15) | (CFG_DDR_ROW_BITS << 3) | CFG_DDR_COLUMN_BITS - ); - + + /* Check if sdram_config is nonzero */ + and t1, s0, 0xffff + bne t1, $0, sdram_mem_cfg + nop + + /* sdram_config is 0, configure by code-default values */ /* Figure out if it's a low cost package */ - #li s2,PHYS_TO_K1(SI_ENUM_BASE) # s2 = SI_ENUM_BASE - lw t1,CC_CHIPID(s2) - li s3,0x00300000 - and t1,t1,s3 - - /* memory_cfg2 register */ - li t2, (CFG_DDR_MEM_WIDTH << 6) | (CFG_DDR_BANK_BITS << 4) - beq t1, 0, 1f + andi t1, s1, 0x03 + + /* Standard package, assume 1024-column, 32-bit, 8-bank DDR */ + beq t1, $0, sdram_mem_cfg + li s0, (0x0140 | CFG_DDR_CAS_LATENCY) + + /* Low cost package, assume 1024-column, 16-bit, 8-bank DDR */ + li s0, (0x01c0 | CFG_DDR_CAS_LATENCY) + +sdram_mem_cfg: + /* CAS Latency: + * sdram_config[2:0]: CAS latency + * PL341_cas_latency[3:1]: CL range from 2 to 6 + * PL341_write_latency[2:0]: CL - 1 + */ + andi t1, s0, 0x07 + sll t2, t1, 1 + sw t2, PL341_cas_latency(a1) + subu t2, t1, 1 + sw t2, PL341_write_latency(a1) + + /* PL341_memory_cfg: Rows and Columns */ + lw t2, PL341_memory_cfg(a1) # Read PL341_memory_cfg + + /* Columns: + * sdram_config[10:8]: 0=2048; 1=1024; 2=512; 3=256 columns + * PL341_memory_cfg[2:0]: 1=9-bit; 2=10-bit; 3=11-bit; Others=Reserved. + */ + li t3, ~0x7 # columns(bit2:0) + and t2, t2, t3 # clear column + srl t1, s0, 8 # Column fields from sdram_config s0(bit10:8) + andi t1, t1, 0x07 + li t3, 0x3 + subu t1, t3, t1 + andi t1, t1, 0x07 + or t2, t2, t1 + sw t2, PL341_memory_cfg(a1) + + /* PL341_memory_cfg2: Bus width and Banks */ + lw t2, PL341_memory_cfg2(a1) # Read PL341_memory_cfg2 + + /* Low cost package is 16-bit bus */ + andi t1, s1, 0x03 + li t3, ~0xc0 + bne t1, $0, 2f # nonzero: low cost package with 16-bit bus + and t2, t2, t3 # Clear bit[7:6] to work in 16-bit mode + + /* Bus width: + * sdram_config[7]: 0 default bus width, 1: reduced width + * PL341_memory_cfg2[7:6]: 00 for 16bit, 01=32bit, 10=64bit, 11=reserved + */ + andi t1, s0, 0x80 + bne t1, $0, 2f # Work in 16-bit mode nop - and t2, t2, 0xffffff3f /* Set to 16bit for low cost package */ + or t2, t2, 0x40 # Set bit[7:6] to 32-bit mode +2: + /* Banks: + * sdram_config[6]: 0 for 4 banks, 1 for 8 banks + * PL341_memory_cfg2[5:4]: 00 for 4 banks, 11 for 8 banks + */ + andi t1, s0, 0x40 # Bank configuration + li t3, ~0x30 + beq t1, $0, 1f + and t2, t2, t3 # Clear bit[5:4] to work in 4-bank mode + or t2, t2, 0x30 # Set bit[5:4] to 11 for 8-bank mode 1: - sw t2, PL341_memory_cfg2(t0); - + sw t2, PL341_memory_cfg2(a1); + /* chip0 configuration */ ddr_write(PL341_chip_0_cfg, 0x00000000); - + /* user_config0 */ ddr_write(PL341_user_config0, 0x00000003); - /* * DDR2 chip initialization */ /* Issue NOP */ ddr_write(PL341_direct_cmd, MCHIP_CMD_NOP); - + /* issue precharge all */ ddr_write(PL341_direct_cmd, MCHIP_CMD_PRECHARGE_ALL); - + /* Set EMR2 */ - ddr_write(PL341_direct_cmd, MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(2)); - + ddr_write(PL341_direct_cmd, MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(2)); + /* Set EMR3 */ - ddr_write(PL341_direct_cmd, MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(3)); - + ddr_write(PL341_direct_cmd, MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(3)); + /* DLL Enable */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | + ddr_write(PL341_direct_cmd, + MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | MCHIP_EMR1_DLL_DISABLE(0) ); - + /* DLL Reset */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(0) | - MCHIP_MR_WRITE_RECOVERY(MEMCYCLES(CFG_DDR_T_WR)) | - MCHIP_MR_DLL_RESET(1) | - MCHIP_MR_CAS_LATENCY(CFG_DDR_CAS_LATENCY) | - MCHIP_MR_BURST_LENGTH - ); - + /* Set CAS to external memory devices */ + lw t1, PL341_cas_latency(a1) # CAS value in bit3:1 + li t2, (MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(0) | \ + MCHIP_MR_WRITE_RECOVERY(MEMCYCLES(CFG_DDR_T_WR)) | \ + MCHIP_MR_DLL_RESET(1) | MCHIP_MR_BURST_LENGTH) + sll t1, t1, 3 # Shift to bit6:4 for DDR MRS register + or t2, t2, t1 + sw t2, PL341_direct_cmd(a1) + /* issue precharge all */ ddr_write(PL341_direct_cmd, MCHIP_CMD_PRECHARGE_ALL); - + /* auto-refresh 2 times */ ddr_write(PL341_direct_cmd, MCHIP_CMD_AUTO_REFRESH); ddr_write(PL341_direct_cmd, MCHIP_CMD_AUTO_REFRESH); - + /* DLL Reset=0 (Un-Reset DLL) */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(0) | - MCHIP_MR_WRITE_RECOVERY(MEMCYCLES(CFG_DDR_T_WR)) | - MCHIP_MR_DLL_RESET(0) | - MCHIP_MR_CAS_LATENCY(CFG_DDR_CAS_LATENCY) | - MCHIP_MR_BURST_LENGTH - ); - + and t2, t2, ~MCHIP_MR_DLL_RESET(1) + sw t2, PL341_direct_cmd(a1) + /* DLL Enable & RTT 75ohm */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | + ddr_write(PL341_direct_cmd, + MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | MCHIP_EMR1_DLL_DISABLE(0) | MCHIP_EMR1_RTT_75_OHM | MCHIP_EMR1_OCD_CALI_EXIT ); - + /* OCD Defaults */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | + ddr_write(PL341_direct_cmd, + MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | MCHIP_EMR1_DLL_DISABLE(0) | MCHIP_EMR1_RTT_75_OHM | MCHIP_EMR1_OCD_CALI_DEFAULT ); - + /* OCD Exit */ - ddr_write(PL341_direct_cmd, - MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | + ddr_write(PL341_direct_cmd, + MCHIP_CMD_MODE_REG | MCHIP_MODEREG_SEL(1) | MCHIP_EMR1_DLL_DISABLE(0) | MCHIP_EMR1_RTT_75_OHM | MCHIP_EMR1_OCD_CALI_EXIT ); - + /* set MEMC to GO */ ddr_write(PL341_memc_cmd, 0); nop nop - - jr t7 + + jr ra nop - + .set reorder END(ai_amemcinit) diff --git a/release/src-rt/shared/aiutils.c b/release/src-rt/shared/aiutils.c old mode 100644 new mode 100755 index 2c8eb9538f..059370c6fe --- a/release/src-rt/shared/aiutils.c +++ b/release/src-rt/shared/aiutils.c @@ -363,9 +363,13 @@ BCMATTACHFN(ai_scan)(si_t *sih, void *regs, uint devid) for (i = 1; i < nsp; i++) { j = 0; do { - asd = get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, &addrl, &addrh, + asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); - } while (asd != 0); + + if (asd == 0) + break; + j++; + } while (1); if (j == 0) { SI_ERROR((" SP %d has no address descriptors\n", i)); goto error; @@ -483,6 +487,91 @@ ai_setcoreidx(si_t *sih, uint coreidx) return regs; } +void +ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) +{ + si_info_t *sii = SI_INFO(sih); + chipcregs_t *cc = NULL; + uint32 erombase, *eromptr, *eromlim; + uint i, j, cidx; + uint32 cia, cib, nmp, nsp; + uint32 asd, addrl, addrh, sizel, sizeh; + + for (i = 0; i < sii->numcores; i++) { + if (sii->coreid[i] == CC_CORE_ID) { + cc = (chipcregs_t *)sii->regs[i]; + break; + } + } + if (cc == NULL) + goto error; + + erombase = R_REG(sii->osh, &cc->eromptr); + eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); + eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); + + cidx = sii->curidx; + cia = sii->cia[cidx]; + cib = sii->cib[cidx]; + + nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; + nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; + + /* scan for cores */ + while (eromptr < eromlim) { + if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && + (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { + break; + } + } + + /* skip master ports */ + for (i = 0; i < nmp; i++) + get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); + + /* Skip ASDs in port 0 */ + asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); + if (asd == 0) { + /* Try again to see if it is a bridge */ + asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, + &sizel, &sizeh); + } + + j = 1; + do { + asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, + &sizel, &sizeh); + j++; + } while (asd != 0); + + /* Go through the ASDs for other slave ports */ + for (i = 1; i < nsp; i++) { + j = 0; + do { + asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, + &sizel, &sizeh); + if (asd == 0) + break; + + if (!asidx--) { + *addr = addrl; + *size = sizel; + return; + } + j++; + } while (1); + + if (j == 0) { + SI_ERROR((" SP %d has no address descriptors\n", i)); + break; + } + } + +error: + *size = 0; + return; +} + /* Return the number of address spaces in current core */ int ai_numaddrspaces(si_t *sih) diff --git a/release/src-rt/shared/bcm_rpc.c b/release/src-rt/shared/bcm_rpc.c old mode 100644 new mode 100755 index b3c79f6e20..6eef3b0525 --- a/release/src-rt/shared/bcm_rpc.c +++ b/release/src-rt/shared/bcm_rpc.c @@ -41,7 +41,9 @@ #endif #endif /* WLC_HIGH */ #ifdef WLC_LOW +#if !defined(_HNDRTE_) #error "RPC only supports HNDRTE in LOW driver" +#endif #endif /* WLC_LOW */ /* use local flag BCMDBG_RPC so that it can be turned on without global BCMDBG */ @@ -51,6 +53,7 @@ #endif #endif /* BCMDBG */ +#define BCMDBG_RPC /* #define BCMDBG_RPC */ static uint32 rpc_msg_level = RPC_ERROR_VAL; @@ -989,12 +992,12 @@ bcm_rpc_watchdog(struct rpc_info *rpci) count = 0; uptime++; if (uptime % 60 == 0) - RPC_ERR(("rpc uptime %d minutes\n", (uptime / 60))); + RPC_TRACE(("rpc uptime %d minutes\n", (uptime / 60))); } #else uptime++; if (uptime % 60 == 0) { - RPC_ERR(("rpc uptime %d minutes\n", (uptime / 60))); + RPC_TRACE(("rpc uptime %d minutes\n", (uptime / 60))); } #endif @@ -1124,7 +1127,9 @@ bcm_rpc_call(struct rpc_info *rpci, rpc_buf_t *b) return -1; } + RPC_OSL_LOCK(rpci->rpc_osh); rpci->trans++; + RPC_OSL_UNLOCK(rpci->rpc_osh); #ifdef BCMDBG_RPC /* Since successful add the entry */ if (RPC_PKTLOG_ON()) { diff --git a/release/src-rt/shared/bcmotp.c b/release/src-rt/shared/bcmotp.c old mode 100644 new mode 100755 index b7c67552db..d57b2fd443 --- a/release/src-rt/shared/bcmotp.c +++ b/release/src-rt/shared/bcmotp.c @@ -362,13 +362,12 @@ ipxotp_max_rgnsz(otpinfo_t *oi) case BCM43431_CHIP_ID: oi->fusebits = OTP_SZ_FU_72; break; + case BCM43131_CHIP_ID: + case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: oi->fusebits = OTP_SZ_FU_72; break; - case BCM43227_CHIP_ID: - oi->fusebits = OTP_SZ_FU_72; - break; default: ASSERT(0); /* Don't konw about this chip */ } diff --git a/release/src-rt/shared/bcmrobo.c b/release/src-rt/shared/bcmrobo.c old mode 100644 new mode 100755 diff --git a/release/src-rt/shared/flashutl.c b/release/src-rt/shared/flashutl.c old mode 100644 new mode 100755 index 8a12bf4d14..a2253ca424 --- a/release/src-rt/shared/flashutl.c +++ b/release/src-rt/shared/flashutl.c @@ -35,7 +35,7 @@ #define ERR2 0x30 /* Mask for err UNUSED */ #define DONE 0x80 /* Mask for done */ #define WBUFSIZE 32 /* Write Buffer size */ -#define FLASH_TRIES 4000000 /* retry count */ +#define FLASH_TRIES 700000 /* retry count */ #define CMD_ADDR ((unsigned long)0xFFFFFFFF) /* 'which' param for block() */ diff --git a/release/src-rt/shared/hnddma.c b/release/src-rt/shared/hnddma.c old mode 100644 new mode 100755 index 042ebe18ef..b953366c6a --- a/release/src-rt/shared/hnddma.c +++ b/release/src-rt/shared/hnddma.c @@ -1216,6 +1216,14 @@ _dma_rxfill(dma_info_t *di) if (extra_offset) PKTPULL(di->osh, p, extra_offset); +#ifdef CTFMAP + /* mark as ctf buffer for fast mapping */ + if(CTF_ENAB(kcih)) { + ASSERT((((uint32)PKTDATA(di->osh, p)) & 31)==0); + PKTSETCTF(di->osh, p); + } +#endif /* CTFMAP */ + /* Do a cached write instead of uncached write since DMA_MAP * will flush the cache. */ diff --git a/release/src-rt/shared/hndmips.c b/release/src-rt/shared/hndmips.c old mode 100644 new mode 100755 index 05ce770443..450333431c --- a/release/src-rt/shared/hndmips.c +++ b/release/src-rt/shared/hndmips.c @@ -249,12 +249,10 @@ BCMATTACHFN(si_mips_init)(si_t *sih, uint shirqmap) tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ tmp |= CEIL(120, ns); /* W0 = 120nS */ - if ((sih->ccrev < 9) || - (CHIPID(sih->chip) == BCM5365_CHIP_ID)) + if (sih->ccrev < 9) W_REG(osh, &cc->flash_waitcount, tmp); if ((sih->ccrev < 9) || - (CHIPID(sih->chip) == BCM5365_CHIP_ID) || ((CHIPID(sih->chip) == BCM5350_CHIP_ID) && CHIPREV(sih->chiprev) == 0)) { W_REG(osh, &cc->pcmcia_memwait, tmp); } @@ -405,7 +403,7 @@ BCMINITFN(si_mem_clock)(si_t *sih) #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) -static void __attribute__((__noinline__)) +static void __attribute__ ((__noinline__)) ephy_poll_phyaccess(void) { asm("phypoll: \tlui $8, 0xb800\n\t" @@ -416,23 +414,21 @@ ephy_poll_phyaccess(void) "nop"); } -static void __attribute__((__noinline__)) -do_router_coma(si_t *sih, void *dmem, int delay) +static void __attribute__ ((__noinline__)) +coma_delay(void) { - uint8 phy; - volatile _dmemcregs_t *dmc = (volatile _dmemcregs_t *)dmem; - dmemsregs_t *dms = (dmemsregs_t *)dmem; - - /* SDRAM refresh */ - if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) { - SET_REG(osh, &dms->control[9], DMC09_SREFRESH, DMC09_SREFRESH); - SET_REG(osh, &dms->control[9], DMC09_START, 0); - } else { - SET_REG(osh, &dmc->control[9], DMC09_SREFRESH, DMC09_SREFRESH); - SET_REG(osh, &dmc->control[9], DMC09_START, 0); - } + /* for (i = 0; i < 3000000; i++); */ + asm("lui $8, 0x2d\n\t" + "ori $8,$8,0xc6c0\n\t" + "coma_delay_loop: \taddiu $8,$8,-1\n\t" + "bnez $8,coma_delay_loop\n\t" + "nop"); +} - OSL_DELAY(delay * 1000000); +static void __attribute__ ((__noinline__)) +do_router_coma(si_t *sih, void *dmem, int delay_val) +{ + uint8 phy; /* set jtag user reg 0 = 0x80 to set DDR pad power saving mode */ asm("lui $8, 0xb800"); @@ -444,7 +440,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sw $9, 0x0030($8)"); asm("sync"); - OSL_DELAY(delay * 1000000); + coma_delay(); /* ephy ports powerdown */ @@ -587,11 +583,11 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("addi $10, $10, 1"); } - OSL_DELAY(delay * 1000000); + coma_delay(); /* ports 0-5 writes end */ if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) { - /* set ephy pll and bias power power save through chipc registers */ + /* set ephy pll and bias power save through chipc registers */ asm("lui $8, 0xb800"); asm("li $9, 0x4"); asm("sw $9, 0x0650($8)"); @@ -600,7 +596,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); asm("lui $8, 0xb800"); asm("li $9, 0x2"); @@ -610,7 +606,16 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); + + /* Clear the dmems ddrctrl reg */ + asm("lui $8, 0xb800"); + asm("li $9, 0x0"); + asm("sw $9, 0x41e4($8)"); + asm("sync"); + asm("nop"); + + coma_delay(); } else { /* A0 vs B0 steps */ @@ -626,7 +631,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sw $9, 0x0030($8)"); asm("sync"); - OSL_DELAY(delay * 1000000); + coma_delay(); } else { /* set ephy pll and bias power power save through chipc registers */ @@ -638,7 +643,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); asm("lui $8, 0xb800"); asm("li $9, 0x2"); @@ -648,7 +653,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); } } @@ -662,7 +667,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sw $9, 0x0030($8)"); asm("sync"); - OSL_DELAY(delay * 1000000); + coma_delay(); /* set gmac dmp io control = 0 */ asm("lui $8, 0xb810"); @@ -671,16 +676,35 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); - /* set ddr dmp io control = 0 */ - asm("lui $8, 0xb810"); - asm("li $9, 0x0"); - asm("sw $9, 0x5408($8)"); - asm("sync"); - asm("nop"); + if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) { + /* set ddr dmp io control = 0 */ + asm("lui $8, 0xb810"); + asm("li $9, 0x0"); + asm("sw $9, 0x4408($8)"); + asm("sync"); + asm("nop"); + /* put dmems in reset */ + asm("li $9, 0x1"); + asm("sw $9, 0x4800($8)"); + asm("sync"); + asm("nop"); + } else { + /* set ddr dmp io control = 0 */ + asm("lui $8, 0xb810"); + asm("li $9, 0x0"); + asm("sw $9, 0x5408($8)"); + asm("sync"); + asm("nop"); + /* put dmemc in reset */ + asm("li $9, 0x1"); + asm("sw $9, 0x5800($8)"); + asm("sync"); + asm("nop"); + } - OSL_DELAY(delay * 1000000); + coma_delay(); /* set PMU control = 1 */ asm("lui $8, 0xb800"); @@ -689,7 +713,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); if (((CHIPID(sih->chip)) != BCM53572_CHIP_ID)) { /* Set switching freq of internal 12V regulator to 600kHz */ @@ -704,7 +728,7 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("sync"); asm("nop"); - OSL_DELAY(delay * 1000000); + coma_delay(); } /* set mips dmp io control = 0 */ @@ -725,15 +749,16 @@ do_router_coma(si_t *sih, void *dmem, int delay) asm("nop"); } -static void __attribute__((__noinline__)) +static void __attribute__ ((__noinline__)) BCMINITFN(aftercoma)(void) { } void -si_router_coma(si_t *sih, int reset, int delay) +si_router_coma(si_t *sih, int reset, int delay_val) { + osl_t *osh; void *dmem = NULL; chipcregs_t *cc; uint ic_size, ic_lsize; @@ -742,6 +767,8 @@ si_router_coma(si_t *sih, int reset, int delay) uint32 tmp; int i; + osh = si_osh(sih); + /* Disable interrupts */ c0reg = MFC0(C0_STATUS, 0); @@ -756,12 +783,6 @@ si_router_coma(si_t *sih, int reset, int delay) for (i = 0; i < (end - start); i += ic_lsize) cache_op(start + i, Fill_I); - /* d11: aidmp(resetctrl) = 1, aidmp(ioctrl) = 0 */ - si_setcore(sih, D11_CORE_ID, 0); - si_core_disable(sih, 0); - - OSL_DELAY(delay * 1000000); - /* Prepare JTAG registers */ si_setcore(sih, CC_CORE_ID, 0); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); @@ -786,7 +807,7 @@ si_router_coma(si_t *sih, int reset, int delay) else dmem = (void *)si_setcore(sih, DMEMC_CORE_ID, 0); - do_router_coma(sih, dmem, delay); + do_router_coma(sih, dmem, delay_val); } static void @@ -956,6 +977,8 @@ BCMINITFN(mips_pmu_setclock_4706)(si_t *sih, uint32 mipsclock, chipcregs_t *cc = NULL; uint idx, i; bool ret = TRUE, boolChanged = FALSE; + osl_t *osh; + /* 25MHz table for 4706 */ static uint32 BCMINITDATA(pll25mhz_table)[][3 + PLL_ENTRIES_4706] = { /* cpu, ddr, axi, proc_PLL, */ @@ -964,10 +987,15 @@ BCMINITFN(mips_pmu_setclock_4706)(si_t *sih, uint32 mipsclock, { 400, 200, 100, 0xc0011100, }, { 500, 250, 125, 0xc0011140, }, { 600, 300, 150, 0xc0011180, }, + { 632, 316, 158, 0xc00157e8, }, + { 650, 325, 162, 0xc00111a0, }, + { 662, 331, 165, 0xc00111a8, }, {0} }; uint32 (*pll_table)[4] = pll25mhz_table; + osh = si_osh(sih); + /* get index of the current core */ idx = si_coreidx(sih); diff --git a/release/src-rt/shared/hndpci.c b/release/src-rt/shared/hndpci.c old mode 100644 new mode 100755 index a6f0168fd5..8c1a356ca7 --- a/release/src-rt/shared/hndpci.c +++ b/release/src-rt/shared/hndpci.c @@ -810,7 +810,7 @@ BCMATTACHFN(hndpci_init_pci)(si_t *sih, uint coreunit) printf("PCI: Reset RC\n"); OSL_DELAY(3000); W_REG(osh, &pcie->control, PCIE_RST_OE); - OSL_DELAY(1000); /* delay 1 ms */ + OSL_DELAY(50000); /* delay 50 ms *//* for 4706 reboot issue*/ W_REG(osh, &pcie->control, PCIE_RST | PCIE_RST_OE); } @@ -980,6 +980,48 @@ hndpci_arb_park(si_t *sih, uint parkid) OSL_DELAY(1); } +/*for 4706 reboot issue*/ +int +hndpci_deinit_pci(si_t *sih, uint coreunit) +{ + int coreidx; + sbpciregs_t *pci; + sbpcieregs_t *pcie = NULL; + + if (pci_disabled[coreunit]) + return 0; + + coreidx = si_coreidx(sih); + pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit); + if (pci == NULL) { + pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit); + if (pcie == NULL) { + printf("PCI: no core\n"); + return -1; + } + } + + if (pci) + W_REG(osh, &pci->control, PCI_RST_OE); + else + W_REG(osh, &pcie->control, PCIE_RST_OE); + + si_core_disable(sih, 0); + si_setcoreidx(sih, coreidx); + return 0; +} + +/* + * * Deinitialize PCI(e) cores + * */ +void +hndpci_deinit(si_t *sih) +{ + int coreunit; + + for (coreunit = 0; coreunit < SI_PCI_MAXCORES; coreunit++) + hndpci_deinit_pci(sih, coreunit); +} /* * Get the PCI region address and size information. */ diff --git a/release/src-rt/shared/hndpmu.c b/release/src-rt/shared/hndpmu.c old mode 100644 new mode 100755 index 40cd75e293..689ed2a40e --- a/release/src-rt/shared/hndpmu.c +++ b/release/src-rt/shared/hndpmu.c @@ -342,7 +342,7 @@ si_pmu_paref_ldo_enable(si_t *sih, osl_t *osh, bool enable) uint16 BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh) { - uint delay = PMU_MAX_TRANSITION_DLY; + uint delay_val = PMU_MAX_TRANSITION_DLY; chipcregs_t *cc; uint origidx; #ifdef BCMDBG @@ -369,89 +369,90 @@ BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh) case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: + case BCM43131_CHIP_ID: case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: case BCM6362_CHIP_ID: case BCM4342_CHIP_ID: case BCM4313_CHIP_ID: - delay = ISSIM_ENAB(sih) ? 70 : 3700; + delay_val = ISSIM_ENAB(sih) ? 70 : 3700; break; case BCM4328_CHIP_ID: - delay = 7000; + delay_val = 7000; break; case BCM4325_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { uint32 ilp = si_ilp_clock(sih); - delay = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) + + delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) + D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp); - delay = (11 * delay) / 10; + delay_val = (11 * delay_val) / 10; } break; case BCM4329_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { uint32 ilp = si_ilp_clock(sih); - delay = (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) + + delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) + D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp); - delay = (11 * delay) / 10; + delay_val = (11 * delay_val) / 10; } break; case BCM4315_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { uint32 ilp = si_ilp_clock(sih); - delay = (si_pmu_res_uptime(sih, osh, cc, RES4315_HT_AVAIL) + + delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4315_HT_AVAIL) + D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp); - delay = (11 * delay) / 10; + delay_val = (11 * delay_val) / 10; } break; case BCM4319_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { #ifdef BCMUSBDEV /* For USB HT is always available, even durring IEEE PS, * so need minimal delay */ - delay = 100; + delay_val = 100; #else /* BCMUSBDEV */ /* For SDIO, total delay in getting HT available */ /* Adjusted for uptime XTAL=672us, HTAVail=128us */ uint32 ilp = si_ilp_clock(sih); - delay = si_pmu_res_uptime(sih, osh, cc, RES4319_HT_AVAIL); - PMU_MSG(("si_ilp_clock (Hz): %u delay (ilp clks): %u\n", ilp, delay)); - delay = (delay + D11SCC_SLOW2FAST_TRANSITION) * (1000000 / ilp); - PMU_MSG(("delay (us): %u\n", delay)); - delay = (11 * delay) / 10; - PMU_MSG(("delay (us): %u\n", delay)); + delay_val = si_pmu_res_uptime(sih, osh, cc, RES4319_HT_AVAIL); + PMU_MSG(("si_ilp_clock (Hz): %u delay (ilp clks): %u\n", ilp, delay_val)); + delay_val = (delay_val + D11SCC_SLOW2FAST_TRANSITION) * (1000000 / ilp); + PMU_MSG(("delay (us): %u\n", delay_val)); + delay_val = (11 * delay_val) / 10; + PMU_MSG(("delay (us): %u\n", delay_val)); /* VDDIO_RF por delay = 3.4ms */ - if (delay < 3400) delay = 3400; + if (delay_val < 3400) delay_val = 3400; #endif /* BCMUSBDEV */ } break; case BCM4336_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { uint32 ilp = si_ilp_clock(sih); - delay = (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) + + delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) + D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp); - delay = (11 * delay) / 10; + delay_val = (11 * delay_val) / 10; } break; case BCM4330_CHIP_ID: if (ISSIM_ENAB(sih)) - delay = 70; + delay_val = 70; else { uint32 ilp = si_ilp_clock(sih); - delay = (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) + + delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) + D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp); - delay = (11 * delay) / 10; + delay_val = (11 * delay_val) / 10; } break; default: @@ -465,7 +466,7 @@ BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh) /* Return to original core */ si_setcoreidx(sih, origidx); - return (uint16)delay; + return (uint16)delay_val; } #endif /* !_CFE_ || CFG_WL */ @@ -2320,6 +2321,7 @@ BCMATTACHFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq) case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID: case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: + case BCM43131_CHIP_ID: case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: @@ -2390,6 +2392,7 @@ BCMINITFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh) case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID: case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: + case BCM43131_CHIP_ID: case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: @@ -2480,7 +2483,7 @@ BCMINITFN(si_pmu5_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint static uint32 BCMINITFN(si_4706_pmu_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m) { - uint32 w; + uint32 w, ndiv, p1div, p2div; uint32 clock; /* Strictly there is an m5 divider, but I'm not sure we use it */ @@ -2489,12 +2492,14 @@ BCMINITFN(si_4706_pmu_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, return 0; } - /* Get N divider to determine CPU clock */ + /* Get N, P1 and P2 dividers to determine CPU clock */ W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU6_4706_PROCPLL_OFF); - w = (R_REG(NULL, &cc->pllcontrol_data) & PMU6_4706_PROC_NDIV_INT_MASK) >> - PMU6_4706_PROC_NDIV_INT_SHIFT; + w = R_REG(NULL, &cc->pllcontrol_data); + ndiv = (w & PMU6_4706_PROC_NDIV_INT_MASK) >> PMU6_4706_PROC_NDIV_INT_SHIFT; + p1div = (w & PMU6_4706_PROC_P1DIV_MASK) >> PMU6_4706_PROC_P1DIV_SHIFT; + p2div = (w & PMU6_4706_PROC_P2DIV_MASK) >> PMU6_4706_PROC_P2DIV_SHIFT; /* Fixed reference clock 25MHz and m = 2 */ - clock = w * 25000000 / 2; + clock = (25000000 / 2) * ndiv * p2div / p1div; if (m == PMU5_MAINPLL_MEM) clock = clock / 2; else if (m == PMU5_MAINPLL_SI) @@ -3468,6 +3473,7 @@ si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravo tmp = PCTL_PLL_PLLCTL_UPD; break; + case BCM43131_CHIP_ID: case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: @@ -3858,7 +3864,7 @@ si_pmu_radio_enable(si_t *sih, bool enable) /* Wait for a particular clock level to be on the backplane */ uint32 -si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay) +si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay_val) { chipcregs_t *cc; uint origidx; @@ -3870,8 +3876,8 @@ si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay) cc = si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc != NULL); - if (delay) - SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay); + if (delay_val) + SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay_val); /* Return to original core */ si_setcoreidx(sih, origidx); diff --git a/release/src-rt/shared/linux_osl.c b/release/src-rt/shared/linux_osl.c old mode 100644 new mode 100755 index dde3239240..2cace588a8 --- a/release/src-rt/shared/linux_osl.c +++ b/release/src-rt/shared/linux_osl.c @@ -554,7 +554,11 @@ osl_pktfastfree(osl_t *osh, struct sk_buff *skb) skb->destructor = NULL; ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); +#if 0 ASSERT(ctfpool != NULL); +#else + if (ctfpool == NULL) return; +#endif /* Add object to the ctfpool */ CTFPOOL_LOCK(ctfpool, flags); @@ -594,8 +598,14 @@ osl_pktfree(osl_t *osh, void *p, bool send) spin_unlock_irqrestore(&osh->pktlist_lock, flags); #endif +#ifdef CTFMAP + /* Clear the map ptr before freeing */ + PKTCLRCTF(osh, skb); + CTFMAPPTR(osh, skb) = NULL; +#endif /* CTFMAP */ + #ifdef CTFPOOL - if (PKTISFAST(osh, skb)) + if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) osl_pktfastfree(osh, skb); else { #else /* CTFPOOL */ @@ -1100,6 +1110,13 @@ osl_pktdup(osl_t *osh, void *skb) void * p; unsigned long flags; + /* clear the CTFBUF flag if set and map the reset of the buffer + * before cloning + */ +#ifdef CTFMAP + PKTCTFMAP(osh, skb); +#endif + if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) return NULL; diff --git a/release/src-rt/shared/nvram/nvram.c b/release/src-rt/shared/nvram/nvram.c old mode 100644 new mode 100755 index bbbaab50c1..c6f8985ea0 --- a/release/src-rt/shared/nvram/nvram.c +++ b/release/src-rt/shared/nvram/nvram.c @@ -83,6 +83,107 @@ hash(const char *s) return hashval; } +//#define NVRAM2HANDLER 1 + +/* + * separte nvram into two part, for those bootloader can't handle large nvram well models + * nvram_header + * + * nvram_header2 + * + */ + +#ifdef NVRAM2HANDLER + +struct nvram_header *find_next_header(struct nvram_header *header, char *ptr) +{ + struct nvram_header *hdr; + char *hdrptr; + + hdrptr = (char *)header; + + if(ptr>hdrptr) { + if((ptr-hdrptr)%16) { + hdrptr = ptr + (16-(ptr-hdrptr)%16); + } + else hdrptr = ptr; + } + else hdrptr = NULL; + + hdr = (struct nvram_header *)hdrptr; + +printk("header : %x %x %x\n", header, ptr, hdr); + + return hdr; +} + +/* (Re)initialize the hash table. Should be locked. */ +static int +BCMINITFN(nvram_rehash)(struct nvram_header *header) +{ + char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq; + struct nvram_header *hdrptr; + /* (Re)initialize hash table */ + nvram_free(); + + hdrptr = header; + + /* Parse and set "name=value\0 ... \0\0" */ + name = (char *) &hdrptr[1]; + end = (char *) hdrptr + NVRAM_SPACE - 2; + end[0] = end[1] = '\0'; + +again: + for (; *name; name = value + strlen(value) + 1) { + if (!(eq = strchr(name, '='))) + break; + *eq = '\0'; + value = eq + 1; + _nvram_set(name, value); + *eq = '='; + } + +printk("rehash %x %x\n", header, name); +{ + int j; + + for(j=0;j<64;j++) { + if(j%16==0) printk("\n"); + printk("%x ", *(name-32+j)); + } + printk("\n"); +} + hdrptr = find_next_header(header, name+2); + + if(hdrptr) + printk("magic: %x\n", hdrptr->magic); + + if(hdrptr && hdrptr->magic==NVRAM_MAGIC) { + name = (char *)&hdrptr[1]; + goto again; + } + + /* Set special SDRAM parameters */ + if (!_nvram_get("sdram_init")) { + sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16)); + _nvram_set("sdram_init", buf); + } + if (!_nvram_get("sdram_config")) { + sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff)); + _nvram_set("sdram_config", buf); + } + if (!_nvram_get("sdram_refresh")) { + sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff)); + _nvram_set("sdram_refresh", buf); + } + if (!_nvram_get("sdram_ncdl")) { + sprintf(buf, "0x%08X", header->config_ncdl); + _nvram_set("sdram_ncdl", buf); + } + + return 0; +} +#else /* (Re)initialize the hash table. Should be locked. */ static int BCMINITFN(nvram_rehash)(struct nvram_header *header) @@ -125,6 +226,7 @@ BCMINITFN(nvram_rehash)(struct nvram_header *header) return 0; } +#endif /* Get the value of an NVRAM variable. Should be locked. */ char * @@ -234,6 +336,82 @@ _nvram_getall(char *buf, int count) return 0; } +#ifdef NVRAM2HANDLER +/* Regenerate NVRAM. Should be locked. */ +int +BCMINITFN(_nvram_commit)(struct nvram_header *header) +{ + char *init, *config, *refresh, *ncdl; + char *ptr, *end; + int i; + struct nvram_tuple *t; + struct nvram_header *hdrptr; + int starti, next; + + hdrptr=header; + bzero(hdrptr, NVRAM_SPACE); + /* Leave space for a double NUL at the end */ + end = (char *) header + NVRAM_SPACE - 2; + starti=0; + next = 0; + +again: + + /* Regenerate header */ + hdrptr->magic = NVRAM_MAGIC; + hdrptr->crc_ver_init = (NVRAM_VERSION << 8); + if (!(init = _nvram_get("sdram_init")) || + !(config = _nvram_get("sdram_config")) || + !(refresh = _nvram_get("sdram_refresh")) || + !(ncdl = _nvram_get("sdram_ncdl"))) { + hdrptr->crc_ver_init |= SDRAM_INIT << 16; + hdrptr->config_refresh = SDRAM_CONFIG; + hdrptr->config_refresh |= SDRAM_REFRESH << 16; + hdrptr->config_ncdl = 0; + } else { + hdrptr->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16; + hdrptr->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff; + hdrptr->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16; + hdrptr->config_ncdl = bcm_strtoul(ncdl, NULL, 0); + } + + /* Clear data area */ + ptr = (char *) hdrptr + sizeof(struct nvram_header); + + /* Write out all tuples */ + for (i = starti; i < ARRAYSIZE(nvram_hash); i++) { + for (t = nvram_hash[i]; t; t = t->next) { + if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) + break; + ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; + } + if(starti==0 && (ptr-(char *)hdrptr)>(NVRAM_SPACE/2)) { + starti = i+1; +printk("next hash table: %x\n", i); + break; + } + } + + /* End with a double NUL */ + ptr += 2; + + /* Set new length */ + hdrptr->len = ROUNDUP(ptr - (char *) hdrptr, 4); + + /* Set new CRC8 */ + hdrptr->crc_ver_init |= nvram_calc_crc(hdrptr); + +printk("commit %x %x %d\n", header, ptr, i); + hdrptr = find_next_header(header, ptr); + + if(hdrptr && imagic == NVRAM_MAGIC) nvram_rehash(header); diff --git a/release/src-rt/shared/nvram/nvram_ro.c b/release/src-rt/shared/nvram/nvram_ro.c deleted file mode 100644 index 05b74b4312..0000000000 --- a/release/src-rt/shared/nvram/nvram_ro.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Read-only support for NVRAM on flash and otp. - * - * Copyright 2004, Broadcom Corporation - * All Rights Reserved. - * - * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; - * the contents of this file may not be disclosed to third parties, copied - * or duplicated in any form, in whole or in part, without the prior - * written permission of Broadcom Corporation. - * - * $Id$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static char *fnv = NULL; -static char *fnvlim = NULL; -static char *otp = NULL; -static char *otplim = NULL; -static char *otp2 = NULL; -static char *otp2lim = NULL; - - -static struct nvram_header * -find_flash_nvram(uint32 base, uint32 lim) -{ - struct nvram_header *nvh; - uint32 off = FLASH_MIN; - - nvh = NULL; - while (off <= lim) { - nvh = (struct nvram_header *) (base + off - NVRAM_SPACE); - if (nvh->magic == NVRAM_MAGIC) - return nvh; - off <<= 1; - }; - - /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ - nvh = (struct nvram_header *) (base + 4096); - if (nvh->magic == NVRAM_MAGIC) - return nvh; - - nvh = (struct nvram_header *) (base + 1024); - if (nvh->magic == NVRAM_MAGIC) - return nvh; - - return NULL; -} - -int -BCMINITFN(nvram_init)(void *sbh) -{ - uint idx; - chipcregs_t *cc; - struct sflash *info; - struct nvram_header *nvh = NULL; - uint32 cap = 0, base, lim; - - - /* Make sure */ - fnv = NULL; - otp = NULL; - otp2 = NULL; - - /* Check for flash */ - idx = sb_coreidx(sbh); - if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { - base = KSEG1ADDR(SB_FLASH2); - lim = 0; - cap = R_REG(&cc->capabilities); - switch (cap & CAP_FLASH_MASK) { - case PFLASH: - lim = SB_FLASH2_SZ; - break; - - case SFLASH_ST: - case SFLASH_AT: - if ((info = sflash_init(cc)) == NULL) - break; - lim = info->size; - break; - - case FLASH_NONE: - default: - break; - } - } else { - base = KSEG1ADDR(SB_FLASH1); - lim = SB_FLASH1_SZ; - } - - if (lim != 0) - nvh = find_flash_nvram(base, lim); - - if (nvh != NULL) { - fnv = (char *)&nvh[1]; - fnvlim = (char *)((uint32)nvh + NVRAM_SPACE); - } - - /* Check for otp */ - if ((cc != NULL) && ((lim = cap & CAP_OTPSIZE) != 0)) { - uint32 bound; - uint16 *otpw, *d16; - int i; - - otpw = (uint16 *)((uint32)cc + CC_OTP); - lim = 1 << ((lim >> CAP_OTPSIZE_SHIFT) + 5); - if ((otpw[OTP_HWSIGN] == OTP_SIGNATURE) && - (otpw[0] == OTP_MAGIC)) { - bound = otpw[OTP_BOUNDARY]; - if (bound >= lim) { - printf("Bad boundary value in otp (%d >= %d)\n", bound, lim); - goto out; - } - /* OK, we like otp, copy to ram, skipping the magic word */ - if ((otp = MALLOC(NULL,bound - 2)) == NULL) { - printf("Out of memory for otp\n"); - goto out; - } - d16 = (uint16 *)otp; - for (i = 1; i < (bound / 2); i++) - *d16++ = otpw[i]; - otplim = otp + bound - 2; - printf ("otp size = %d, hwsign = 0x%x, magic = 0x%x, boundary = 0x%x\n", - lim, otpw[OTP_HWSIGN], otpw[0], bound); - - /* Now do it again for the "second" part of the otp */ - if (otpw[OTP_SWSIGN] == OTP_SIGNATURE) { - if ((otp2 = MALLOC(NULL, lim - bound)) == NULL) { - printf("Out of memory for otp2\n"); - goto out; - } - d16 = (uint16 *)otp2; - while (i < (lim / 2)) - *d16++ = otpw[i++]; - otp2lim = otp2 + lim - bound; - } - } - } - -out: /* All done */ - sb_setcoreidx(sbh, idx); - - return 0; -} - -void -BCMINITFN(nvram_exit)(void) -{ - if (otp) { - MFREE(NULL, otp, otplim - otp); - otp = NULL; - } - - if (otp2) { - MFREE(NULL, otp2, otp2lim - otp2); - otp2 = NULL; - } -} - -static char * -findvar(char *vars, char *lim, const char *name) -{ - char *s; - int len; - - len = strlen(name); - - for (s = vars; (s < lim) && *s; ) { - if ((bcmp(s, name, len) == 0) && (s[len] == '=')) - return (&s[len+1]); - - while (*s++) - ; - } - - return NULL; -} - -char * -BCMINITFN(nvram_get)(const char *name) -{ - char *v = NULL; - - if ((fnv != NULL) && ((v = findvar(fnv, fnvlim, name)) != NULL)) - return v; - - if ((otp2 != NULL) && ((v = findvar(otp2, otp2lim, name)) != NULL)) - return v; - - if (otp != NULL) - v = findvar(otp, otplim, name); - - return v; -} - -int -BCMINITFN(nvram_set)(const char *name, const char *value) -{ - return 0; -} - -int -BCMINITFN(nvram_unset)(const char *name) -{ - return 0; -} - -int -BCMINITFN(nvram_commit)(void) -{ - return 0; -} - -int -BCMINITFN(nvram_getall)(char *buf, int count) -{ - return 0; -} diff --git a/release/src-rt/shared/nvram/nvram_rw.c b/release/src-rt/shared/nvram/nvram_rw.c old mode 100644 new mode 100755 diff --git a/release/src-rt/shared/nvram/nvram_vx.c b/release/src-rt/shared/nvram/nvram_vx.c deleted file mode 100644 index 74518b9688..0000000000 --- a/release/src-rt/shared/nvram/nvram_vx.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * NVRAM variable manipulation (direct mapped flash) - * - * Copyright 2004, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * - * $Id$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); -void BCMINIT(_nvram_free)(struct nvram_tuple *t); -int BCMINIT(_nvram_read)(void *buf); - -extern char * BCMINIT(_nvram_get)(const char *name); -extern int BCMINIT(_nvram_set)(const char *name, const char *value); -extern int BCMINIT(_nvram_unset)(const char *name); -extern int BCMINIT(_nvram_getall)(char *buf, int count); -extern int BCMINIT(_nvram_commit)(struct nvram_header *header); -extern int BCMINIT(_nvram_init)(void); -extern void BCMINIT(_nvram_exit)(void); - -static struct nvram_header *nvram_header = NULL; -static ulong flash_base = 0; - -#define NVRAM_LOCK() do {} while (0) -#define NVRAM_UNLOCK() do {} while (0) - -/* Convenience */ -#define KB * 1024 -#define MB * 1024 * 1024 - -char * -BCMINITFN(nvram_get)(const char *name) -{ - char *value; - - NVRAM_LOCK(); - value = BCMINIT(_nvram_get)(name); - NVRAM_UNLOCK(); - - return value; -} - -int -BCMINITFN(nvram_getall)(char *buf, int count) -{ - int ret; - - NVRAM_LOCK(); - ret = BCMINIT(_nvram_getall)(buf, count); - NVRAM_UNLOCK(); - - return ret; -} - -int -BCMINITFN(nvram_set)(const char *name, const char *value) -{ - int ret; - - NVRAM_LOCK(); - ret = BCMINIT(_nvram_set)(name, value); - NVRAM_UNLOCK(); - - return ret; -} - -int -BCMINITFN(nvram_unset)(const char *name) -{ - int ret; - - NVRAM_LOCK(); - ret = BCMINIT(_nvram_unset)(name); - NVRAM_UNLOCK(); - - return ret; -} - -static bool -BCMINITFN(nvram_reset)(void *sbh) -{ - chipcregs_t *cc; - char *value; - uint32 watchdog = 0, gpio; - uint idx, msec; - - idx = sb_coreidx(sbh); - - /* Check if we were soft reset */ - if ((cc = sb_setcore(sbh, SB_CC, 0))) { - watchdog = R_REG(&cc->intstatus) & CI_WDRESET; - sb_setcoreidx(sbh, idx); - } - if (watchdog) - return FALSE; - - value = BCMINIT(nvram_get)("reset_gpio"); - if (!value) - return FALSE; - - gpio = (uint32) bcm_atoi(value); - if (gpio > 7) - return FALSE; - - /* Setup GPIO input */ - sb_gpioouten(sbh, (1 << gpio), 0); - - /* GPIO reset is asserted low */ - for (msec = 0; msec < 5000; msec++) { - if (sb_gpioin(sbh) & (1 << gpio)) - return FALSE; - OSL_DELAY(1000); - } - - return TRUE; -} - -extern unsigned char embedded_nvram[]; - -static struct nvram_header * -BCMINITFN(find_nvram)(bool embonly, bool *isemb) -{ - struct nvram_header *nvh; - uint32 off, lim; - - - if (!embonly) { - *isemb = FALSE; - if (flash_base == SB_FLASH1) - lim = SB_FLASH1_SZ; - else - lim = SB_FLASH2_SZ; - off = FLASH_MIN; - while (off <= lim) { - nvh = (struct nvram_header *)KSEG1ADDR(flash_base + off - NVRAM_SPACE); - if (nvh->magic == NVRAM_MAGIC) - return (nvh); - off <<= 1; - }; - } - - /* Now check embedded nvram */ - *isemb = TRUE; - nvh = (struct nvram_header *)KSEG1ADDR(flash_base + (4 * 1024)); - if (nvh->magic == NVRAM_MAGIC) - return (nvh); - nvh = (struct nvram_header *)KSEG1ADDR(flash_base + 1024); - if (nvh->magic == NVRAM_MAGIC) - return (nvh); -#ifdef _CFE_ - nvh = (struct nvram_header *)embedded_nvram; - if (nvh->magic == NVRAM_MAGIC) - return (nvh); -#endif - return (NULL); -} - -int -BCMINITFN(nvram_init)(void *sbh) -{ - uint idx; - bool isemb; - int ret; - - - idx = sb_coreidx(sbh); - if (sb_setcore(sbh, SB_CC, 0) != NULL) { - flash_base = SB_FLASH2; - sb_setcoreidx(sbh, idx); - } else - flash_base = SB_FLASH1; - - /* Temporarily initialize with embedded NVRAM */ - nvram_header = BCMINIT(find_nvram)(TRUE, &isemb); - ret = BCMINIT(_nvram_init)(); - if (ret == 0) { - /* Restore defaults from embedded NVRAM if button held down */ - if (BCMINIT(nvram_reset)(sbh)) { - return 1; - } - - BCMINIT(_nvram_exit)(); - } - - /* Find NVRAM */ - nvram_header = BCMINIT(find_nvram)(FALSE, &isemb); - ret = BCMINIT(_nvram_init)(); - if (ret == 0) { - /* Restore defaults if embedded NVRAM used */ - if (nvram_header && isemb) { - ret = 1; - } - } - return ret; -} - -void -BCMINITFN(nvram_exit)(void) -{ - BCMINIT(_nvram_exit)(); -} - -int -BCMINITFN(_nvram_read)(void *buf) -{ - uint32 *src, *dst; - uint i; - - if (!nvram_header) - return -19; /* -ENODEV */ - - src = (uint32 *) nvram_header; - dst = (uint32 *) buf; - - for (i = 0; i < sizeof(struct nvram_header); i += 4) - *dst++ = *src++; - - for (; i < nvram_header->len && i < NVRAM_SPACE; i += 4) - *dst++ = ltoh32(*src++); - - return 0; -} - -struct nvram_tuple * -BCMINITFN(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value) -{ - if (!(t = MALLOC(NULL, sizeof(struct nvram_tuple) + strlen(name) + 1 + strlen(value) + 1))) { - printf("_nvram_realloc: our of memory\n"); - return NULL; - } - - /* Copy name */ - t->name = (char *) &t[1]; - strcpy(t->name, name); - - /* Copy value */ - t->value = t->name + strlen(name) + 1; - strcpy(t->value, value); - - return t; -} - -void -BCMINITFN(_nvram_free)(struct nvram_tuple *t) -{ - if (t) - MFREE(NULL, t, sizeof(struct nvram_tuple) + strlen(t->name) + 1 + strlen(t->value) + 1); -} - -int -BCMINITFN(nvram_commit)(void) -{ - struct nvram_header *header; - int ret; - uint32 *src, *dst; - uint i; - - if (!(header = (struct nvram_header *) MALLOC(NULL, NVRAM_SPACE))) { - printf("nvram_commit: out of memory\n"); - return -12; /* -ENOMEM */ - } - - NVRAM_LOCK(); - - /* Regenerate NVRAM */ - ret = BCMINIT(_nvram_commit)(header); - if (ret) - goto done; - - src = (uint32 *) &header[1]; - dst = src; - - for (i = sizeof(struct nvram_header); i < header->len && i < NVRAM_SPACE; i += 4) - *dst++ = htol32(*src++); - -#ifdef _CFE_ - if ((ret = cfe_open("flash0.nvram")) >= 0) { - cfe_writeblk(ret, 0, (unsigned char *) header, header->len); - cfe_close(ret); - } -#else - if (sysFlashInit(NULL) == 0) - nvWrite((unsigned short *) header, NVRAM_SPACE); -#endif - - done: - NVRAM_UNLOCK(); - MFREE(NULL, header, NVRAM_SPACE); - return ret; -} - diff --git a/release/src-rt/shared/siutils.c b/release/src-rt/shared/siutils.c old mode 100644 new mode 100755 index 9dec182743..297fe87c18 --- a/release/src-rt/shared/siutils.c +++ b/release/src-rt/shared/siutils.c @@ -585,6 +585,37 @@ BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100); OSL_DELAY(20000); /* Srom read takes ~12mS */ } +#ifdef BCMQT + /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF. + * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz + * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words. + */ + { + uint otpclkdiv = 0; + + if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || + (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { + otpclkdiv = 2; + } else if ((CHIPID(sih->chip) == BCM43227_CHIP_ID) || + (CHIPID(sih->chip) == BCM43131_CHIP_ID) || + (CHIPID(sih->chip) == BCM43228_CHIP_ID)) { + otpclkdiv = 4; + } + + if (otpclkdiv != 0) { + uint clkdiv, savecore; + savecore = si_coreidx(sih); + si_setcore(sih, CC_CORE_ID, 0); + + clkdiv = R_REG(osh, &cc->clkdiv); + clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT); + W_REG(osh, &cc->clkdiv, clkdiv); + + SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv)); + si_setcoreidx(sih, savecore); + } + } +#endif /* BCMQT */ } #endif /* !_CFE_ || CFG_WL */ #ifdef SI_SPROM_PROBE @@ -726,7 +757,7 @@ BCMATTACHFN(si_detach)(si_t *sih) #if defined(STA) struct si_pub *si_local = NULL; - bcopy(&sih, &si_local, sizeof(si_t**)); + bcopy(&sih, &si_local, sizeof(si_t*)); #endif sii = SI_INFO(sih); @@ -1104,6 +1135,16 @@ si_addrspacesize(si_t *sih, uint asidx) } } +void +si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) +{ + /* Only supported for SOCI_AI */ + if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_coreaddrspaceX(sih, asidx, addr, size); + else + *size = 0; +} + uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val) { @@ -1365,12 +1406,6 @@ BCMINITFN(si_clock)(si_t *sih) else m = R_REG(sii->osh, &cc->clockcontrol_sb); - if (CHIPID(sih->chip) == BCM5365_CHIP_ID) - rate = 200000000; /* PLL_TYPE3 */ - else if (CHIPID(sih->chip) == BCM5354_CHIP_ID) - /* 5354 has a constant sb clock of 120MHz */ - rate = 120000000; - else /* calculate rate */ rate = si_clock_rate(pll_type, n, m); @@ -4005,6 +4040,8 @@ si_is_sprom_available(si_t *sih) case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: return (sih->chipst & CST4331_SPROM_PRESENT) != 0; + case BCM43131_CHIP_ID: + case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; @@ -4046,6 +4083,8 @@ si_is_otp_disabled(si_t *sih) case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID: case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: + case BCM43131_CHIP_ID: + case BCM43227_CHIP_ID: case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: default: return FALSE; diff --git a/release/src-rt/shared/siutils_priv.h b/release/src-rt/shared/siutils_priv.h old mode 100644 new mode 100755 index b2c07d729a..ee35209414 --- a/release/src-rt/shared/siutils_priv.h +++ b/release/src-rt/shared/siutils_priv.h @@ -221,6 +221,7 @@ extern void ai_core_disable(si_t *sih, uint32 bits); extern int ai_numaddrspaces(si_t *sih); extern uint32 ai_addrspace(si_t *sih, uint asidx); extern uint32 ai_addrspacesize(si_t *sih, uint asidx); +extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); extern void ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val); #ifdef BCMDBG diff --git a/release/src-rt/wl/mipsel-uclibc/eapd b/release/src-rt/wl/mipsel-uclibc/eapd deleted file mode 100755 index 3a633bde2b4f7a93a54d4d8f1471b0188a66a922..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 37619 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 SoP9Bej&d}_gIUN?1^+*I6n2vU diff --git a/release/src-rt/wl/mipsel-uclibc/nas b/release/src-rt/wl/mipsel-uclibc/nas deleted file mode 100755 index 470272ce080e18d47649f1c58aa964a1b55bd94b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 77820 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 diff --git a/release/src-rt/wl/mipsel-uclibc/wl b/release/src-rt/wl/mipsel-uclibc/wl deleted file mode 100755 index e57c7ef0ff82c54532404d94f83d2577410beb15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 360057 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≈7cM=30z;_^#kK1E-32k9tR&LQ(= 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 #H$=@8A7}`@%B} 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 z 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%0D9c$8HvP0}S0P&mi7nl`EI` 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 nXYd5n*IH91?WS static void sleep_ms(const unsigned int ms) @@ -1030,7 +1030,7 @@ wlconf_del_wet_tunnel_vndr_ie(char *name, int bsscfg_idx, uchar *oui) break; } } - bufaddr = ieinfo->vndr_ie_data.oui + ieinfo->vndr_ie_data.len; + bufaddr = (char *)ieinfo->vndr_ie_data.oui + ieinfo->vndr_ie_data.len; } if (!found) @@ -1121,7 +1121,7 @@ wlconf(char *name) char tmp[100], prefix[PREFIX_LEN]; char var[80], *next, *str, *addr = NULL; /* Pay attention to buffer length requirements when using this */ - char buf[WLC_IOCTL_MAXLEN]; + char buf[WLC_IOCTL_SMLEN*2] __attribute__ ((aligned(4))); char *country; wlc_rev_info_t rev; channel_info_t ci; @@ -1249,10 +1249,11 @@ wlconf(char *name) if (bcmerr == BCME_RANGE) break; } - if (ret) + if (ret) { WLCONF_DBG("%d:(%s): setting bsscfg #%d iovar \"bss\" to 0" " (down) failed, ret = %d, bcmerr = %d\n", __LINE__, name, i, ret, bcmerr); + } } /* Get the list of BSS Configs */ @@ -1275,7 +1276,7 @@ wlconf(char *name) /* create a wlX.Y_ifname nvram setting */ for (i = 1; i < bclist->count; i++) { bsscfg = &bclist->bsscfgs[i]; -#if defined(linux) || defined(__ECOS) +#if defined(linux) || defined(__ECOS) || defined(__NetBSD__) strcpy(var, bsscfg->ifname); #endif nvram_set(strcat_r(bsscfg->prefix, "ifname", tmp), var); @@ -1390,7 +1391,7 @@ wlconf(char *name) WL_IOCTL(name, WLC_SET_INFRA, &val, sizeof(val)); /* Set The AP MAX Associations Limit */ - if (ap | apsta) { + if (ap || apsta) { max_assoc = val = atoi(nvram_safe_get(strcat_r(prefix, "maxassoc", tmp))); if (val > 0) { WL_IOVAR_SETINT(name, "maxassoc", val); @@ -1398,6 +1399,8 @@ wlconf(char *name) WL_IOVAR_GETINT(name, "maxassoc", &max_assoc); } } + if (!wet && !sta) + WL_IOVAR_SETINT(name, "mpc", OFF); for (i = 0; i < bclist->count; i++) { char *subprefix; @@ -1431,7 +1434,8 @@ wlconf(char *name) brcm_prop_ie_t wet_tunnel_ie; wet_tunnel_ie.type = WET_TUNNEL_IE_TYPE; wet_tunnel_ie.cap = htons(1); - wlconf_set_wet_tunnel_vndr_ie(name, bsscfg->idx, BRCM_PROP_OUI, + wlconf_set_wet_tunnel_vndr_ie(name, + bsscfg->idx, (uchar *)BRCM_PROP_OUI, (uchar *)&(wet_tunnel_ie.type), sizeof(wet_tunnel_ie.type)+sizeof(wet_tunnel_ie.cap)); WL_IOVAR_SETINT(name, "ap_tunneling", 1); @@ -1588,7 +1592,8 @@ wlconf(char *name) if ((rev.chipnum == BCM4716_CHIP_ID) || (rev.chipnum == BCM47162_CHIP_ID) || (rev.chipnum == BCM4748_CHIP_ID) || (rev.chipnum == BCM4331_CHIP_ID) || - (rev.chipnum == BCM43431_CHIP_ID)) { + (rev.chipnum == BCM43431_CHIP_ID) || (rev.chipnum == BCM5357_CHIP_ID) || + (rev.chipnum == BCM53572_CHIP_ID) || (rev.chipnum == BCM43236_CHIP_ID)) { int pam_mode = WLC_N_PREAMBLE_GF_BRCM; /* default GF-BRCM */ strcat_r(prefix, "mimo_preamble", tmp); @@ -1601,6 +1606,18 @@ wlconf(char *name) WL_IOVAR_SETINT(name, "mimo_preamble", pam_mode); } + if ((rev.chipnum == BCM5357_CHIP_ID) || (rev.chipnum == BCM53572_CHIP_ID)) { + val = atoi(nvram_safe_get("coma_sleep")); + if (val > 0) { + struct {int sleep; int delay;} setbuf; + nvram_unset("coma_sleep"); + nvram_commit(); + setbuf.sleep = val; + setbuf.delay = 1; + WL_IOVAR_SET(name, "coma", &setbuf, sizeof(setbuf)); + } + } + /* Get current phy type */ WL_IOCTL(name, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); printf("%s: PHYTYPE: %d\n", __FUNCTION__, phytype); @@ -1785,9 +1802,8 @@ wlconf(char *name) int control = WLC_PROTECTION_CTL_OFF; /* Set n protection override and control algorithm */ - strcat_r(prefix, "nmode_protection", tmp); - - if (nvram_match(tmp, "auto")) { + str = nvram_get(strcat_r(prefix, "nmode_protection", tmp)); + if (!str || !strcmp(str, "auto")) { override = WLC_PROTECTION_AUTO; control = WLC_PROTECTION_CTL_OVERLAP; } diff --git a/release/src/router/prebuilt/wl_exe.o b/release/src/router/prebuilt/wl_exe.o new file mode 100755 index 0000000000000000000000000000000000000000..b9ec3fb05e01d4bc92a1b7ceafa513f49f8fbe83 GIT binary patch literal 264560 zcwX$idwg71buYf=%t)FfN<3B+dy<%B#y%bi+n9-Qg98QzTYdm(>o^Xiy}(Z>&Z9u7 zd9+P0w3#d0;G3VSGl@-N=caTjS++7&0Sp8%c|a%$I1eCggXgaA zT6>>!X6DRDPW$K0=i_K*_G|66*Iuu^_S(0sxN>DI79;y#jFJ?5BWnK#huTs^i{)E4 z&7@9xbz0>`s`>Aix7bg!mJ;3Fl|8v5PSo!u=_LOxl*7M|SH9G>guXnsnC=_P(~+?S zbaw z^Wd`5UY?7`bMbgC9?yl_9`txFJjQ;H=OTD0(3iTjea9erd%jYbf$y(Y@EgXkaP$oL zu;dk%Co7byRL*xB!Fm?YB}Vav=P&aPo{SeoS(FN{< z@)u(VYj}d!(B(C(U$1=w(r2ki*$hd)*)3&4ze!rQAQ-dYV7w%cmCX~w*fq%g)!-}> z?`E8#4a(7`wvP5;>jm(gWcbnypTgAd<5lNL0uPsaS;hp`CNqWh30gjo?JiO)^)fyf z6k1=^UySFM7J7*8b07D4CHJ|Sj*ay&?H8E#mon`yVcK8Jw4Y~OE?``C`?%c7FqZl6 z$Aw-xLGMDbJ7kRT`nK@;chVcV4PQuU0@iz2)paq7TtbHzV-d z{d3g-{=ZE2ZGkd$%sW|mD#!h#X3_8%;J5Hz!F9Av{ak-lvHNy*KmOlB@00J`htz$( zvRvr5n3}wJw5`1*>d|zNX$YzR8xcnDp9k5>d_bTbL3p7{kbuO$K zYg)uumNt?`K47eKYTCV2Dav}a_`f^yd(xK~^>lk4cwKkF>7=ze3)lBS2MibEs-fJ- z3m*yhS9Hu=Q`%QGU(PVzt9f!iXqSRDTp6rku~>yyJBCj`OYr+9({7U+qZVnmh+3PL zcTZA2XOi;QPf|XAlJdE>ywSWe`a9N|@f9I+qGX-LC)#1J?qYe~=Hqcq-*Kdwm;jnS6;Bmb7)z2cz#))TPt{Qfk@@y zKJ4=tXhmVS{B~89e0o{-X|igc3T>o|Tw`SkvJK;@Y}>&)#Y75YDh!U>68f$<=tX^z zzdGJj^aJo=-uGKrKPa&-*RAWa-K-byAKp*-y$M>hw_YCz=7+NOvzHH`JVA5zq8#;t zIsq*0G^9F7p808afmpvuFx`-a8*OU&*KvkF&+so`-qp=>aCr`P{S)-qK(qn$N<_;qans`tKbf6jCo<5v&DkozYXK&dC{bNr&q<-n3wW+%!>~)A2`7C+i%u& zT;N;6b84skGS06mvpaO0T3t{1@i|OCSVNWnpu1iNbRLEY^`KJ%wnqKLRW~E>8P!9S zhEZo0jdY>^SxloTk)z8&JoGh|MS!iH`P)g+Gpp$$kP8twWgfMV`6+bAFidvLRzoAx z0hh=@g{ht94njAqoge1L`@-`XfbuV4Gh>9KNS2Zu0ab? zYtMCNVC}d}_GT+hEI6;uzF6V!Eqqh@*d*gYXUAL~^vBxBx>_r3V7)^0HId6q-+LdQ?)1m*_r4`-yFzq>Z-hSoYv}W%q0j&1f8ODN zc7)FIqVLqv(5;nT(I;+;pr4~mKLw_rW_ojizRu(12D78gW6EXv1dTJDLr={(3C0&u zpWq6*D(gA94}<11;{@0;A=p$$t%mJN0(~c3UiXEdzw;SSvxE*eGap(sSiO%5vX4Fx zK~LfGKM>o@aTyO|aqhR%r;E)@PnXs7sk+3wYx=CU;bwCm22SZ0a;Q@2TST+sG&kKx zXqzObgMS}G9bRhDn`RmPGq8<8)0=sJmHqvd4AFHGJS|foOSfqnxid_+pdntbhB{|9 zRTTcV+UPj#5o4jB=MAsIoTl2}o(k-Wp|NrESMgMEGBxy9yT)G-`b)T9kD$L%roS~z ze^;{owwmp?9;U+r)8SI4!zE0Ii2Q=~-ch3eH3=>LMTi!=!?ai~P27KGQKqxh-(< zfcb0bxr$DX*01+nhMxa9f}Y`vTgvp@n3sOTg{=ZR4K`bw*ioS0LL~iyC!WnTYf5XgwSf&66MfY3EVcVDV7iVQ-L;*rAB3G$%SS{f;PvG> zH{~Dj)uCVXw~G2w=tp^>_FKybe_m0VQu%IWIM-b=4my*$R4R|;Q5SkqR_u>x{Ctt^ zTDyOu%CWxy*FK-GMb|r2(@*UlJ66#>cCXm^iZ|4mj6dFP=xMJ{PtiKdF0nTf?o{+Y zwNK0C82@wlU!4CX_+JbE1HH9UhtaD?%zkQhA=9#%>5RvIZroRjF+J-3?IqA6>#r%u zw-+iMLMN@{yrotbgwHO}2cz`=us;sGbz*>dcU<8GowbQQ2c2dHbfzNchxO6pz14n; zbiv0{tN7kFal4Uf8z9Y=kJtc~7JGf&-|$v0rrB?R1R`Tc^P5a2b^o7*FUWuX-b8bbrkQZ{@ibX!wp# zT)KJ_x)UY28izsTC}SkITm zN47o}#u?hz(4ODVFWDABKjCuU{`YYm?XM5xo@Lrz-TSaJ*p>>-`3c4c`uj@doigu# zi@^Vx_vu95MX%G4S8t4>hnYYV)@(#w!@&#G0UZQX1eus*pHz#<`Z)Y5; z9W{Fp(0qYuGh_4viwlt#Tfnm(@b10FaqqpRh1Y&!FV;Lk`}e}8Xs4eHrf9_HF-gkj z)aRn`bP5eU!294CmAzcXaxadu5P%0#eeCXssGZ> zd2UFqRMW_a;P4LP$JTl6%)z(v#aOHI&?Sl&z)=O4!PheN$B`97N6QDnaQ z`!st7{2ccPZIp$U!aNo@2aipMc_Mz&2gWO5yb+mOjE3^><=+Zh&Sx8U zKYcN_Y{6|6JKuVKjK2St$NxaJG1X!#2ULT3EUnmYDeF6_#IC6qYCI z`2Qy37cK}MHgfrIWxQy3K3!LC+IK6CKN-&s^)ho9msf@j1b^?O{GqU_P;w`NR_D z6N{NoX@IvYf|E7U!!5Ddg*2VSEpcCj%SJD@~uG9>2Q_HEH=6Z8e?-SUVemv-YDsxn}pMc)Vbn}-L zoDZ#aA?xPud(5#oPlxQNr;{nccc7zgC~&&f@(P=r}ccamlfq?% zw8MMg%T;kcAqCY>ppHfG?1W;CDzODRk)n{ zv%c?jco^fV4HLu`pudTkamwa0xJ0G;Wgii9BU6%)6TAokRblIb;B5Vw5crF?} zW|+^Rzo4Jz4gU_~DoQ_^ntu9u4|^6mO_KKKpi91mI^Aq)jjT&t_U83Wd^C(Le{&2nxi*G&Jjx?ipB(#>#&d9d=b3Gw-c?SfX=hTY?IQ4^aW zO*=&&yVUUGa9KV63%-rOFx2sZd=nc1u;9E1I(vJ~9>che`aAPAQvI$(SG#h?W6pOd z)9Q*ZmUZXVjB9~&%Sj!-=6nuyn$cfO&ZBYmRB$vlCNm?Ox!Tm-x);7frhli|+P218 zTc*2}s?<}LxO zLt~H5xk6w^j0JRx=i!4W!Dqc+@Rl%o@aqh(1#eLsjQ3G$x}&3w@SH*H zm-*?q=qbO(eld0JT7c)OZax{@(K^(N;MLrA@^kBrp3>9}1F%cu)Ov4;RvuNjS?8&- zJ+n1@9JD>1_g0LiSMlp`y=j6Q_(P^g=yd8w!JZ4B5!*e|T|+y+G;t~5dkN`p>hTbe zkK$X{UL@T^YjWTvIEzwWrQ)%exuS+%=MHN99@V9ag-HH^a{SKt%PC%Wc(<9eqd2W$ zEpg3J@P-8MFYLia@d$I4tdw(8vA(>9_2ny>KQWJCJNqE((Fa(M-tWs?qT6KNI1>Ww;7N)bH>WUe9<+PE zM7dlT{;LiACANQACg0jd@mtTK#I4h)<<|45_12lxc58y-cePW?T`6k4t3bvk zPHMaBVoKhM_@*=^?{ZmZ@1|X2>Q~#zd|~&PrMoY{@$qHMGeYq-~Unhr2EIzI|I0?oN<8@;_^soon!0X2P?*Y~`_KTij*S7Unzd{Yi@7-%f2q32M3j zTuKhvbFna;{8Po!c|APYlJ1kOJU-&9i0<@YgCt0GqWP%}&Ojv`KeXa@ZTqy)C;Vaf zJtnbU59MAGpZnS>e;Dh?DfAN_yPNe4!FzW!TqwJr+x?nxqd38TwK!SHI9XLXuOVJq zht4&)IgfFpJX-Nn%L|HAz|qHj9Km0BTNREz9Eqb%5jb)u!BMq-vzU3wWbw%AQ&YIX zpTju3*qn`EO;ul2U#IG*%S&i;3-#q=bYouOTc2Cj?GVo6i>#YFbdu-w2>-q-=g8jv z9Dm;J!#+PfU2yZ9$Yj-f8Rn*O#~R)iZ$}*#uhR+!G3E#MpIywql98w-EK1P|lW9<8c@#i^= zJLvdW6Qx(DAGC@%(t^aZrc4=rCn`uxYY%@~4#S&e`E_~dHI|058LR(1Y~(<}oX>=5 z^I_RT7a16eblK&sn}~juO|K*9r3w0YnSa}>^15#jIQd88E6b)%I#adngY$5O{~5$N z3cs?pR?mRKHe!91LKl_FO!u{oQ{ONAROq|Hw!^c&&DPkbh4D|ydC$x$z32F8-d8c+ zS23om7}HgZ=_2+V+eQG-7EC^alGM{m+)O@uJhnWEABa$ieA%3sI zx&m|zZYzDF&hHX#K=kJ{u5sJZOuVHT+*JYkxMBl$l8r#D9 zue5&~4RyQ&{iMn!?w~nOhV2a4eq7O*hbo(v*C#9!7fYO8Z3-^U;vhh#xg)O4*{SEe!>@Z#9nV=i-$tfR#?B2p-W4*D~oB8v(0!RJ)$7O$w zxKU+aY*Kc>FAMg_65b=@yhk43eQ}ic#Ub7o`$GGIXnYUgBs#eVzQXL5aRR+%OD9$T zVp)m#SwEs(fB18tU*jwozO1&IU;K(ek~h$GGtrHy-20W88TAD2UHF9-+64vOElQ z5~a^yRO(|;n#Oh%GI7LI=pNtI1wUpN;NGHf-iU8PY!k+S-wk6dpunEV$UJs1&Y>r2 zti0kNY|}Th*Q3jt#fD^$Q_RR1Qn}e8vJ0_6@PW^&jf-Yjo5h)6Y}Cs%fahPD`ta*{ zyx#R8T1XwP`o-$`XEt-bW8!#<^>I9FJ2j4Hx}5(c$azatth|loskL>&_czkA)+H}a z8%xaROG-bVWqJ6ylFFi?u}&Uq7A10)c4v_zaSZmZh4uYK`+Fz9)0(A;Zt;yDElPZ{ zW6lUNj31Ws7wP$=+K}(3^I2}(#<*EklHEZsr3&db{xqRFSgMa;*JSf2slav(?;EF6 zd^;n|zuSgl##Wk_TIBpf^oiS?IjNc49}TJRc53%lfeZA5b$Jf{+oI#3|DOo|PgUJP z8fTqNXG*DcsG?(h;>QR5#Dp-&YSRE z@Ng&dokPs$DK(AdOg8oPxY8recdXs^jKCE$u|D93ucK=^0OS1Bo1Bc{Gt+3%BG&O{ zXdil3fj)4K@Uu#B2IAAh^pEya9q*aSH8W6OXqw^2xTy0K;~e9*(qoA0t&-Dr9LAN$ zxMCZC*CNJi5#zOBTYzx|UDab;d1+${6pSqZ9|m;Zsl?XVyA|^z?pDv(Zc8NQ<)F$6Jd-F%Czbjjp-tWkXac6GNllCpXjyHh4t%T4CN0NzwkdHIWIjE%v%tv8xgrB19Tyy3UrkQqgwlT}hzc#LW^0@~v-^4I) zW0*^HY;1t##TJ$qn^;~HSzdgG<;BfBmrwCrHu$>9W-q(%Bw$6%>p+55ZFA|ty*54` zFn7~ecFm)Sq51S6^Yw@JF5rK8{aeQ`JeUI6xgmh_Dd{Y_JZ z|2nSsqnh?hxczlgX#X~I2EjIfxr;f}k9g*bN$DJV%SV|PD2_AE`$II2_U{LO*j^y* z`jIqNNIleEBXb|OpT`8s^>tQ#|ORcBh8rpnq z>s#;Rhkh(@F448RPHgH{H>&QhU>oG&qmRN-*~ih5x-*5K-mj&Pa%3OBY*O}Yld>N- zDf?cNvTrsi+bCreS@xMGWq;bF>^^_I$!+VjJ(pu0XB=k<+x0w>?GKGzXBxNsCz}$# zkbHkVWje;0&a=k@9S8NttxU)xhM#qucV5AAz1PVu(e;OIEd3U3zXeBPikLpC={e)a z?nl|_)<$1SU4uAFC@g6+y2DQ;K1l7$LKST&oEo?PZ_~8nWwpYxceN!U6Rl7 zm`|2s^mOT!%F0gEaj2j7+z`Daw)IJ}ecQZ3O5XPPJRH7?jV0>P{5-F68-|P9OzZ?)yrvgq3-FD6WlxS_O)xHF3@g!7 zew#{VS-zNdXijFB$L(|HGu)>uo89bcJqJn)4<25Sr_8x)ZjAeIX!dP%QJk{r zKJKS44=?$g%n(5v69$C$Mq=)xN!QUerOH9)4 zrEC{woqvy>+q{KFhlQ5QIAc@UlcC`| zv33_4J5ys>j(7}%$1r#dgU2v<41-rN^sezM8gDWnF~6%y{C6ARaCqD$G!ztMPiH19qFcknxzxvjyh+VI$x2=KBrid)n{2-_yU*ISA6CvrKiK z+WySu48e5B$9q;K|15#$N-Tx@zzQ zo>EK!{yu>p`_s-L41a;_9u4q`eTp;j@ID=#(mqv~!ub3_RoqwgJRd$?y{}IByhp!3 zSM&YZn(t57d_QTv&zR!6f7`6bRMzgRp|yL?tlf=%JW@Tqf5fj}U$(wU*#|=7TvSoL z2%lTcn9XP!YZ%^df8^sg+*kcN{8?xn6c;TG@qqeQhx&c|w58)PO*fAb$N8KqX9Y$0 z58ZdrkfHa_3I#hfA$m^6=PjE{QMigx{&v_l)5%$QsoA%`LwesRMy}BF{8Yk$o;atw zM7ED`TsZo%`NOJnirMp`@YqT_rz@!(#!Qi(6)@A^&_8ysTNP6aIe@Zn`*I~1 zqY-TNdmzAZH{FBa{0`-L*X2=fXRJ?h7L3KL4}Wr5_ItGAvyIBu(2D*>Wvgk$ z?TyNG%;5JV^~gLL#n1+AqUVTm=E3=uF&o3!mw$`-oZ!z3&F3V4o^3v-`16dI^)vP5 z&o-Y6{Q0z@=OTZ8(b9IJFaHz!In$T_zEAV@`?L|PC|gV`2E)HEF>{aV>t?!oPRvufb& zd{1yk0Arj(n&Y;@`UBDMU^a6b#u$YDJSV-8Z8pf1{=Iq+aOd7mqXUo9PHzv5c-iB6 zFZ~Cwea$^?hkD#`dN>E!k|6bI09MT9(7XRY_Fvw}x3+Mc3IEr7r61cxil60!9}ycy zY4<8xCUfg(vJSl0Jl<;_?=_G2n#X&M?eIf&aSz}jCmP(TSxr56P=@W{QyXOuJw*|F zr+s6d+8xH-XY(x*=h5a;5;j&}s*^vT&HpNu{(LR(u{Qs;lkS!JvUQ9P#qo9d2kY)C z1o|cFB#7j0Qjwf_;dq{`+z)ee`b?9 zX$F0v@8>7E7jMV1zyEix4f?sXiO!F5@P|&+;XT`|P7-wz&Fj3%G88Gra z%li-V=Vn^Im-odk$R8_@>unIy+$|r&FPHMnQD1}`n-M_(r2y? z=`)uaeFpyRHgY2MHMD=TPb*W8p~g8ub^gJFU5I}|zc#jY2F{AhHm4}bodb=pxSe_N zJ`+FIV&Z&za)|3ke8c?o9MLb3V>r<;$8d29@zTM3lB{FA%sR#?)-j%A`S2|37*Df~ zague6Cs)Oe)-fLQ&p*M(?&LkVyi}r70>eHU9!5OeE3|V=V?~)yWLn+*R31LS z{{Y`X{+klsf;f%HyFR6}XrQQau&6kI79HCIfLq(U*p=`^S!v| zuus=n`^CM~6$AF%Ae&d6t%WXOzS`+({`BBn!QL&LOY3C4-$7TW`dGGg(a2VbAtc@%CJoR=_7cuW%> z(}c$~;W15kOcNf{gvT_&{CGd}W2LEAnBOW~JLE2_!?cN9Q2TgqLyjkWIk0wTcDvr2 zSucCJZ!g*~-FVw#Z8_ZG)%D6a+0la0v&*g7?HR|yTcYJ+r(S?HH?dhqS$9d$1|Gjd z@(;lmu6QiUScsw4c|Vl1zt`@mQw{bM;$=~OrueXNm2-^z+#~Ujfcv!Q)bF4tJ1MjF za>VO~Y3WZuH~ihUpB-x7NyroVBQgZF(?>D~} zD`l~pKH>ASYFe;yn$73|=O>2k=!{452QWy2k<$AwrK%e1pe;gr?qw+vV z>~OJ6Gf88G16f=hBb6hYCs28G3k@w;C;qV(vi`A0oBGFu*HCQ^UD&0yd3eq-c|I`) z?zGt)hKLV_z7mEDeOBjzD28H}qI4y>M}Nj`USfQrU8C}!Pg4HWB<0_qr2LUeeLQ%E z*YgCgXSL3u@pdzru8==Na9u3QUfCl1a)+U-jUHmg(La7G(G4zgmtt>$M`TT0LW%nJ z2+rhObCWln?U|2qzuTyP0JMjgq|Y1vU}^9Tyk^@>znI6NYijPyGi5T|RdV2DC?4Fe zXW}3(WVl^37o3BkY&Go{n$WzMdQOb*7Z8l$kuI+1h0lqlKe^vjkKgZA?I-*f}AN^Stfo2@r05O2D)jU$n0CEonevOFeawLBaKOEmPfOcD4E>XPG-Gos5$L!v$HDJ)ViBX?QpKxQK>!>s-{=r1q1}qsPpH zVe=R^*4y@by#^l}>g0s->ZIZOFIMVf1J3-e^F~j7nPMw!BU&@)u$`bd-?{rD+BKXt z`x>5jxD zA@At9jNf@QA$eTSqlpFoo8d@_FADjRCq!46>b+n~^EM~9o;BKdD22`5IkIt|DWUt> zLkh3LbxQ89UB)`i4TFI1dzFb!zy=sMuuk$Rxg)(c$2@QGr$k3tBf7`inbuO&>1sTx z-XTx09d$M#U*JslQ$|N|Q|}|ROUN0Awtb`j9t&{h=CUTYjkSAP$oIKQ{guZ4()v3m zt-qA(w~~!1eaNqGbL*d|*ckU<&F-e_CARWg#t(Hj>x*UT-4%xWn<$i%Zc*go4f_*N@uIex9r?<3XORa#8YR$rz=RM&4G_ zQ+CoES^91lWFG9$^QbUG?^p3}OFA6A_ue?iPaE6BHpfpDzhBa!eVjr2Xg%v7>sbfJ z9%Y;y59wQoTLazf6o329F7VcIbJq^|QQ8H632dHmUayB}cUR`k)(@vRxRf+M>qE3( z>K0SeN$)Jh2P>5p@ej;^J)i0IWje~x_K?Ywi?T~thgRR3<tV*eNn&%^sz7-H)2rIA~j@6~a61*%0_9_^09TRd`Q`E&i~q6Y^Ku`~9N^ zuT$l%0beZ*KALqgNSTFp_(rk}$bP(f)=3 z&C&aC!#*_ksBOQwI`?R5>ar)m&z-VPj3Zflr_mo2~7QTek;-=Z*gD(;mS zmrv#tzW4fgMP5eWdPMl?vXHJ0SgZAQYvX@2Lf312A84XRr^OxE>bpRK2cdVtk0&v+ znT(_IVOJOO{m;WuCE?A<6@%6;GJM_e=|E1T&HbzkX?W}FXmo3u{(kF4bnjNS)3;ti z_iRNxB`r(R#k70trL=47+-t9k&E=g)>sZsd@+_Kr?T7jMyI3J=Bf7km=H^$*cypKB z7?bfPx!+Z5hgm<0>d5gk_Iu&Z>T0Hm80;#RTk}%iAmm9vE=R=JE{4x2b-h!m^pueA zC`OOCsPpfY^{JTn*@lEpe$VF-iYv&eupIC3@4#;3`5;fz3emmeG?XvoasD?!;mpmmj zGrpvaMCQtO)f4&|P93j2#qpwb8+og%Ca;&>yZ;a&51QqlRK5Ch^3EIbMic#%^}hpM zd;au_T!!$5ORIYcl{+=}fY#OW%W_%fCkcXl2k-tVY&sJgen4Zxh2MM*J|eajFmXocAyy-jn1#%Qj@L`3an*)P1G(MM_$9G4^> zp?N=u!9zc`4(5b%*{dP`5#DDc|JCm?;OPD{*k^%`#cKf`$udXxHuT8+AY@CI@fBh0 z`6Ay({5u(0qsLl!vZQupcn#CCSM^OC$RxNA;b)=#9UYECb5#Y1WrdCil!}fgTe}PjTej0+bXtQU^j32jP3!@1KRFHJQ3?d z8<`Ij8Ek>N%bFLOn<^KYF}ULAvv^_+8(U#Z41d|xrf^B;q+ zu`HOVEJJ+5;(4hxOk8?~%Xax1tVlyd(; z>X3u;^EkEU;CCx-2bjTLyqWi6k@wPbu$BWgLddW0<^~jf~jB^o{qxv&G&j z_yhk${acA?vhU2T8HCR#C;TDEf$?U^fuT8>lA-e};5RRC`GN-w$(^is)ZHOj;pU`l z6YJc&@0?A$?nFPeap=gYuJ&)#8+<2yUu$*FjJAe!cs|*?Vne$v+~PMgwvL4#uuo;& zM&q=adn%AII#$2;pvW7&55juEZqyCG5jdOcb=SP{^F#4#w7Ke&);ww7Wf@`Ll*D)2 z-i>JgHNU;K{pSX4a}jO7Y}&Td#|IBZ$jYha=GF5+yz7FzA8g}~7O6y^${|PIx|SKP zl{a&ZyeZM2?X`O-n=kq?5vn8EeBXV8@LkUoKi6$J^dBdM@qFxmi8T)M)r`^G%(+(H z>NV@R?M6ShKI*J%aTfl9=iZ8UPSVI-&^(uKI8Rr*nahh6I~VxGKqJ!!tLa4H(cEnC zWmr10_T`B6y-S{o;5-g_GKvm#w8`MI`Go^~vR+w(&*K$~&l|b_#9$%Cd?mGtG&k=$ zdL3&{3A)N%*Yf0oZ2Bb5Y*WgMLbx?CYC(K(|6oG$TP^2x-?$h3u50OAz`Bj#)Y|5_ zUtBvcyoHH7vRD(`H@AFG$MfS{1oj;f{*uXk{NY^l4-ddTL!b4z=BX~%eA=hI*@Go| zQx0)v9TdcC*2;0Ex6L*5Rv*Lpg3wwj_gZr8qwisY-Klq%!7nF|iP4-!^YslNY80!K zGCVtYV?5&wQYas+jZtBJ1#tu6n3Dk3=)SwCd7RXnLvd0kE5SS7e_b=aeOH0&v?{C` zzcby$SYnLVnY%~m>wNP$ps8wqPW^k{(e)lO^`gqp?0#zXxz*kXJ1vmWjo&A(U3XmRKb=h$bQHOpRoRz>N1_9@l^|)&GX6GcF>P` zEj(TekJrNEweWZ?BJ(G&aRT3O#@XfTruB@3zu-)j2qLk=`BGyY|(w zjDehg-0%e0QP5$|X4_*ro$uRnz)gj5$72S3Z;SH1Ux}WP$^jnKeyQ@fw6|xG`2D*+ z&#^GO+Fsghpq_a zNw0+!vV-yJFL#yjN89|BZ@$FEc3jWmR71_fHjl!!rzHAkTEY z#_Qx=^*Bc>weN&hmq+0q?|`E0o`!V2vWl)pBIr7>U6h7x{$TiPUH;c?be^ys-x<<( zEWGE1-i)3_yI6MZu6jE<6Ux==a(Q@e@}7a{@Zoc&$#gf3XTF4j+{YNJQ*3dYBdc0J zI~R1A*E>cyXS;=Z^7CjTYxw=$?=W`iD(aUQwcq8x=nwj2bqw)%NdMG$1k_2JI1t1= z2{_d4#%;{##X=cpE<3;OW-+>M$Fzg(&xs@e1bSQ=z^G4l9 zeLu`LNi}^|k8#Y5(Wv}LlXCkW6yA_Ix8_}^+J1JLevUCbz}HtR)j3UT>u>kRt@r2G z#5Bn|WW-Lv$7*@4@6GDnhqUkt=*fKxkc)Ym`QBmd>M&g=48E;hW9`{CZQ~?0-cahi zAo3kC%z7qJfB*i>&by)4K<1RFIHY_3szHq{UgLfYZ~cs7p0##`wg2&72|nFUy(_Xc zSE7D%R|GzmWrL{k7rw7nV_LHE_Sk20EymX!zN4|KCf{p#t=i2yJZW=BDJJlK-aD~% zos0V$+2d-DXN}zhI{>o8<}iky?U2=_gS$AkU)Yd%PaXX*3{CHIG|DI5Z)}0^ngL(G zuBfcd7Be-v8P0o^W|sQ0G}@j4znLmbmfr%;7RTsA-nACHyT2bJ{g1jatM|s4yde+U zCqWPDVxlj#Y}I5{k~qRu%FnferXH8`_pld#d_^&+tCu&2-Xl2RH32mNMUhhn<8<^b6HlB** zu}d1Ci2lGs^h{A>;$LUVE}`LJ1CJ-|^SYPt+eL)?Ni5rsk6Rmxl%MS~a(S~q7tkDh zuWi)k+iO1l4F3f`sg}iMUlxaX(yxUc5$DiSWsjcnfB%2Dh{8pn*G9!WuMioB@?lDI5i#LS)bC>Ym&~r3bWakX?##NZ-0dFa@FBM-w+%9lsabtZ}sux$s zIW&vIddc^j+48wncEr!?%7ga5^zDch%Z;`+}WT`K2&G0L7l~+I-5gv)`!mVkTVjw)=|gWLH|?kd^)a$ z6~Fx{w_hJ|7WbBj_8*RDe|>}YOC#FQJ3|4eDGOs*`O{XHBS1I-(B#t`j=aI@21|QGD39lnX4ccQKC$bcAaq-V6EZ zzw9wBdrZsTO=jQSO!l73$Utv{_riObf56X$K7LWj$ax0t*I^&Eiw@H=n4s3dB(<^b zKg|5dksJqzed(b19dzU&O0wWDrc#=v=e%V0N; zvw+*69@^P@@SQfFV|AR;8s67e@}6EzeqJ&edqb?x-4MG0Zzc?+={@Ex+tmXpde=ZF zy?cQ5FP7)KnePrW{~cvMd=Kk}_p*-o_hZ0e0XSTueu}V;W%EZ}N{YXN!JoBjkY^Wi zw@vQzZo-{l)=h`w8Hw|3_2n!2ND59>7pTw;dBm9MJzUiX&VfzW-AlFknt>ypx5xAL zRvX-0Yxu6kV{pek_zi7e@OkItvGaf-jr+Cvj3aRjr851ROx}!QQFMfCMr{(wqapX9 zA*Tun)Yn+~>O096Ce*vo__m;X+q0wd#E-F}p=^MSUmN=#_;LD8jtJXc#;Wq!N5v^3 z&rUw}<+>a@VS3V7-5Z&P-c?F49f6)QOg}Euj?&OQ!xDQ?92XqDf%mR|e|$?(*6sIs zz8N~$1=|PkTqf@d*4w_&8#TtGH}NKx+sI3L0m-|Ctn>9%`FSdGMxe22#<0r_JhqrHMX(@-IiNxvzgUx+ewQVEQ29k$U0t5&uuL&!<~rembgT*YYO%6>@-_ zEqXifu+b~gN;gj57=@3wL~D<3qxJlK^XN9Z{^;u@Hw(^3`^&RTOjm+7mhIg$#1;j* zSoEEpC6VXk3i~%I1&K>*RQ}JEMzM)nJ|X9@9UtW5H|1AKYW__>ruKz{6|16J|w%y9(G}jLAx#MMDS5$pl z6?XtPZBZIdT*pU7i_R!$7O!C?J(ECk6ynAUyRs;CmA1U6Zda@d#CQL z$zc-mXSeWrmV{Ra@%)(@ABDbgU0og?6LE2neXSA~N@RG|0BFO$xqx<2a$xfFfE{{A zxm=bzZ-TGw$UD5;WgEiFmNxL7SSxTM4jeg@UX*c$_MVBa_!7jwX6C3q)ot#A8=6iM zVr#2)1&bR?6HE{NmLA}%pX}~gt#2H;%4AIASN*{h{T9%Zpoc;q#d_nO73h7>o-4Yt znX<&rD}C)B!+Vu7#uANVwRf#Rw-^^^+pThs9C~wsYJCh*XABy5Q}2(co?o@T*C?+d z<|6kRW3%UF%i}^v(Ak8hVz~cUl)SFsjhHKFF2!{7#6MhN&T#jS`F`Bg`?xa8`K zOP<))Sg+xSpA}j_u80yn;#%A!j6OMo^v&y-Igfu}4EYXlcS`S5+!WK;>XukR-g$zZ z#ISk{tH-c<46DbmdJL<_uzEKe9Bhx-v!S_z_U`y`*gM;mu6|MJ6J+zjkducmEgq`6uMaF#VvlND91-@!{ zv$?y}tMh_@GUZ_GU76W_vAjhV`>&SpTNju!s7{sh#wB^5nL< zmPeP_`^6h#$g|Vy?4lNTLoA3NLY?!>y(O+A?TfT5|MNON+T&LDukvzs4Dq&`s_3*4 z@9B#v?^!) zf&QYuAMdCc^C9V%Z8Y~x`);r6yM8`&YU3j8b=3Q`@mVcxvR1WsvMp@QX>MyxS%9m{ zWB--;)bp;%VTp!g+G~L01^-Q$dN{uNTlmE?&fBOtF2nm;VC1#(f`H(5kmV2F7ao#c78!1cC*GLmTILiNKlJd__QvTPIly9D-{4Xad zzpt*``W?&8yC!Lib^NqnCn!H;-sE0x%J42oHqCZcnuz&^$9%(MzTq+7@R)BzG78*6%8ROzbTSo8}}#z1Nw1WY3?5Pxu12c5XJ;^34s-DKw_6S)RzN#NU*a zcP@-yC!=F#<=l0%r~Vp!s~J8U)Jd6hgE^sGKML3FUKp#B|7i`w!xFwH-bx3Q<7|CcJ`kn`d9b{3|Dw--9mzR@~DhtPPm`W#rb_f8x684+7; z?ZFm`yJw4ifp>IU-A)=FyF=!VbNZr;y?_#tZ&)?@onltj7UXx}IsArl55m=B`i63V zPjfDB?pX(GLjIai%$&#O3ue5{LQ}{Ujk@@4y70arW-1Ckz@u`V>U^Vtud`>+=8kRz zo0W?;AA#QeSG;EYdn6-~x`l-S?}DHv5L< zmw#^AF7!F#+A~v?Q8!fGmEwK{M&O}L)_1Vchb^eD_jc;*PfmY&ZuoUS9vSCnONGDV z+)HCX;FE*j_9F3DA}+KnbQ_aBoyv(1BvWw2uiMRENOK|u{@s0QE1KAf3(vq8?ixE& z{px@b@m0!`epu->Z+5p-#i3}tU62n^#!lDMSJZf@`(4vMjK3h~>wT=N9bsMVFzafE z#vWpRH_kYHfN^@10$*{AI+o%-D!tlsIqn|`ooyc{8*g(0IM|1^0*;B^M9Y@UA9d(Y zsN6xXuDU!y>*e7QFKbKl=RCGTD>AfnHLKJFFvhATIP{ zG$G@!p>fIc^Kt%;*vr2(zt_v-ao^Xaxoq!anR$d|=3$nZhdf?C*7**2ynfzM3f_LO zxo!7_bI6tow67-T#}1}Jf{k59`!PgL!5^Z*S>qC??KWt8+!HX%ayOF-N^f6;r&((M-`3C|IlET5cSvBDctprhIUgoDzZSTQC#%kyaeggu%XxFJgL&?y_t|19qjj3OQf=l2+Q!o=fP zzErOtA2s^%OmheGsEJeE0KQV`%R6sz=m_;DZlO=)@&4w3!~*u^|AhZ8>+Ybab71Iq zVV(_Li|5L=>M^!e?_*u(2+Q5WEO!sF+&##0_kf4|@8co5c-F{U$q3(-%qd|^+wvaRqlu7Qe@vBJm0=Q$iLzHA9MXV<}URo3GWW} z3r}2V-jDOBAaBAQGX5NSbH1`Hk2sRKrDcw-cZu=w?BluVp6N9)3(ts6#&&DxIo$ts zRGh(mjom`a@_+$-SU7&fW8-Z_+vg3~Yx!~Kz0^Acc`hsrXp45p8D6Bdm*aQny9IMb zgF4Db)uw?TMejxSds{^=u5_d1BF0i4pmGU#1%6-KIx1a&uYe}74=sN|-!~hW&Le$a z?`)nUc=uU&$GxMC=eT?k?wJ8^_|8*tFX45KBX)zo3*NYmu2s?KeMbMyjH~_mHRC5W z=gI#fV-^Gt>YrH?i3e??I-`xVl~@@b_erzvwe9wqcK|K_8*89{*m{V$!x+uR|51dG zz}~GH1L;vFQE?}pZVl5kH`0Te2>TXczln?_jr7d z$7enq&_j33#$u6^G4~=|KPM{mw=WnT^>CNvQKt-#`nid>4!_HAq{=_M&D-+fYuwdz z0I_DgS7*B6y5EHCg$#f!IIg)yR`XoZ_oJ*=zd>ZYx#w!)WOf?8^hgqvp3-6`)8)%l9aE64*qjMkX9m}K zrKV2W)WLq@J>+3e`Ft>=e0`d!!~0)&{8`LbM?(AH)tWxzHRE2ybu*@pYwF<46m>4( z`JED85{(C&&v&8V;l76TrkQ#!*L&4pYwP#2I`Iv@UYuQ`{QAUcs~1Q2n=tzVeuHzR z@8CTgjHh&@zP^V}BOcCi<9@w*-y7ON_o;>B$mx3hJnGIh`b^M+17zMgl3XmT=bjH+ zkol#JU9@}=pP^??%!I5D{2cR)US54STKTWN8_jD+>SxbLzvzD!k7xTv?mqM@{(qA{ z!se)Z9peptQJX8t&G!k7aeL9TeH!alxq&_!!Gb#>;kiH$XjB)uaq#ACj8-l_v%4-| zH?kf3^J@3a@{VnhqUZuJ;I0I#5lbzvu6vU-Q>e?+Gehoo;@lNElzYhLcBoVmi!D6` zIg~fa8S32BT2kDzypgx33S@DIaReXT)-M|MR$AG&p^y_BIw16Z+h?$rySnUJK3B2% zzw8<6NY$AM?x|I7X<3T$N@ZlR+kHJ*x`I;}oC!TY6p22t%}eS+8Z1lvfH`B_u`U61%6;@D5({q%im4`q*nrg#sXf=#6P zWoH_j$k;;z7FYX>?KaKNNmCMd_tDNfQC^}Jxtp+0_-VCo(UyUR8E)2(k4?e9*jwda zw0N=mQ}VS*+?~p|M1%L(E0vCjx7d}QKO?y(iH0TbB;GzB-KuY~Cw*J!I<}GC411{P zIDO3L-f8S0x+Lkpr~SMB+wA%qY^0~m+wAs@?fVVg+c&yn^rRbSy>YMkJwY#~C^q|Y zhh9pNGy8Ii&%V4;xhns4+1Hnt_1HYf>*obJyWSC4M(R6(FX*-4*TOhb1LKeB$?m)O zx4Eeo2(V!O|0wp?1+H!L|8qIsoV0Cb(vvC3jUDp#xXwY|4iDk$h`c|Z^l|e+?xQo* z$Jyrn@j-ciT>BWUsNPB`{r>Zcd6PV;-^;eV&abUF`l8xWtm}=>r1m+BDCxML!MZV? z&oaLH78*CP87JlMP=)IfVl>qLsU!p*z0617&wTV+=A-MFkFGI%G&@=*D;we0?xusxn;scZnQ3KZ zucPv>b4U%C!B~th zkMZR(zC6a4$N2IXU*4J!f7w9xj>X6z=5l4tTz_Ho<}1P144-e$R_k%kD7{g_+_AkF zXMJSkxyi9_<je(r|5!!w4}RA;M|sp+c;m=}Z*rYzp6>HV@<4 z-4{=i_b|wL9{pCH(oUgDCy$zQFy9)vk}s3xyXrR#)*;BNUHfj1wZ*S;p_9p*x$w_s zNOFEG2)%3CZTv5bOf10yLko!8TP*iBkn33U30yvj&jR`LW0Y)Y@8RBJ7HB5b>+|8W z+yc%qs?T!I6`eles*iujQ=d-8fxU~n%Xm}H`uve6LF{s#gXZQAzmcP7$jEC3+Ugej zQRnoic^^55pNRYM6Bw)8#7-cGNN|p&XBN+Zr(}@VFDZRZL)v!vFZ%41=iC&wM(rT) z&~_?&5c>}?1Y*0&+h999c^AHWoGupqt!VVyg5fPBd2nF*I!ZOpmtp(yW0b1;(Rpfo(hlTqO32&1p|~R5#vr;0wlUa8prFm9Q! zCw-o~rJmtkm6}d&YBfDk6Gx$YZ>8+J1RdX_^S)}2r9pk? zrqQ|=L+d^@zl8G1#|CQiZV0b5{$cDT?7x`286V8W|Pf?>ANl8%Wt_Ac{iJiomw>|%DCEA5C@IFFd zXRAJ~FsT18>P_AtHssjYV!Cf^vUhv}xwy`iH{+nwZ9hqf>lgf-8aF&~yc%ys_;9as zv#II4W>?cXmXQfstNW^e*r(mBZyom9s5db`^$D_g&vtYFnUjJ^3j1#As_v)UTdB5t~fMGn2GxrqE^rT&RFYiz1zYGKS zp}AAadu!K3->uXY$HC^{QY$&GZywdWszyTO2z$mX946TM*kn)*aJ%0EX@<#6DoW zHL)R2V;@-8h&gU&L=42;&j-Fn$u$?_HHjVacx;cy_IPZs+r&T=YGNR4uI#jlfq-v( zG3_41c-Q_y`{nO)ZkGwgLDc4}4(`Al96QPT&hm$w2SS1bTqxt+P3BN%S(j zsk@NtsV=8`b<2kXJp*md6B*eey!&yVhJgQ!gLB36ginvSHrJ7D2lzC;|DeY>@fauG z2@3qZ8qcphZYRY>H?+Kt=dEKb(fF%ijfZ88C8t%l<#Ui1s|IY`5o8AHoD^Qy(ty_; zsM}lDlIF$G+^9ocwR;QuO8way7t$#*Fubn{k-0IHM;w^a{%TgY%4Xp`R^UChG|T*WAIqKuMRidSF0sQ zMsQY)eJu1=l_vw|(M1Pi01m}v+2HbkKc3N@WRIVW$d!S5Q-NnH`&0E7eX|SaE1Fw+ zMGpJ3cJE=Y0zS3#)ZTeKWami?4qY~g@0XdoMAdpjrYip6y-Xi_?qu=uT!mTzBgP#y_Y?M*+!u{tM%fR2djN6tEsTrcELQe< zQO|!Z3|Wb>Sdp_l+Ujp#HFX312V(`XhBkh2B0>*}k_F*8P9_6__jr$uUCDaXYSyEA zcwa@mshJ|1w-ION-*m~mFLEvIWL+!F@6|uqgS|Rh@O?}|Z}N8Q^+Ip&GVdVY?fY5O z7T`Xauk93BlKPeQnc@D?=NsXZ90jg)O){Y~w2V0ud(_X5SMqQsH=gdG)Y(oB?=Qpl zLR`C>>hb$H&*-~EoXpiwv@%~32VVd#Z+)9-leb@Jx z$N2Ub-;Afjk#BWky{;vD*JQW|ny9@$n51R-Ya}iZcf?8_@;Il?j^}XRCiYml*U=n% zeFK%s+T7gy1lyhOY)y(Cdfi|bTm7w)i+*K3LEBi4_siO-ZTiD5w4X=g7vmhSn3~D! zw~iE^4TDMX+g~*xXMH8i-yKw*z02wc4)B%|d9w?7xjPfoGY_#A8PTIZnZv!-jL7i~ zgE(tx!TIngY|LV3k}k{jnR5>NCcK-PpbyA=f0LV+I_-R);RIas{JRjfd+3HLe{@;) zY}v82X6Y;(e|)`vZlU(D(2*Z2t~xMaPMw{QcMlc6{fb|v8O84=w~N;ba3lAso9d%C znsu6G<}#D49jvfqEZu+2>M{y5=>4_PO|YLbVyEo%62GkOTliFHKUsRUz5~$z8+?2q zr<|?VHAtbj>6zxfqWRs_3Cgc9kD#CHCH@__ME&0gF6-ao zTj0Yqwfh3fyELbR$V@p;xn5)@cvzT!rH#zQ_!k(NIg9a&zr|FCk(nBAWXrp#&|!V` zX^}VA=W2P^TziI^Y8+1==uOe_5f_`d8SL{M6=v8op3hPc3lx6a@|lo~+FVoTdm%c< zI$J)5w%-Z0b3^_e(7jvZ-+8p6`L%%~+h>^W0-C#C*7SS6ysP$S>suPl-iUmBz+b;n z)d$tCDn_m$#+qh)+jjkCFwU@sc!Q=bhIgF$QqbE}U(s0MS1UP67~{Z^D{&n=>6AH_UhJnmuWJ%TeoswVx_X?Plz+nXwzu)C}_9 zl^%N?!)MnoBRWetbbe8EEQ~)?zqC*9s28U9M}69g9`jrt6Lf_;N1){}y`V2kGj`0U ze40_cycs>-Zv2f{^RGtmiDvJ%G}5aZot?}v=SShQ6Qu)v3t^r)N6dzF(pJJbgzBW3 z8lBYYxaWq>XVG5q8lBe*v?A@&Z7nw$n?r(tl^l-eY~NqIo__v@G|C>?_IL?bXV4)P1;tPgVVQ z^>^(O$eAenA-JFX4*za4_RGY83Fr64*mx(ZcFnL>;^#K^HNtxV z^(2p1x9wZ!QlcJ{hlU*W@imgAdY9g>Z*r|AYw=k0?Loog)Be7w&U62?!CiPxKWbo` zMd$AQ`hcF12YQlkLl@N#ZO2vITKfcg&~)J|^Fy|JLgFemd%(ZOrRzGk9qtNrs=~?VpJyvRG0!*-)iFSkP`;;xzNm~LK_yHN6x~3HD_{iUpJMy z+@WQQE;s$#K2G`PcG0$i?OS99_ly4Z%=;M2r2AMV9pOECxZ&B;>N-BlykomLt3Fzw zzo`^vL9bK1SQu7RopnCt@55*qq1OV=@ZLjtg<2LR7;mUE)AvWz_rW%=sZ;1I@MqjN z%kW>;?K@NacY(hqJ0zDF+F?AjL3|+a)2v_M4*f>eDVRD>bDd0sIvG>v2V5uBpiauv z3GTksoUwP0JK=o~n$WyxQMKDU1^DQC9ux2Be0HG3`d5-Rme6OMT9}8o-dmy-M-$X~f0E)u z%A=s;E_0WFKePT8ryl0tJxAY0!&@9-m&3oWsQZ1nOR=H+QUc!_9;^D@ z8OpQWo$9RpJu#HWeVuge@5!M&-l>~a`+I6Ak9USMwZCVE@_299t@?eLKj&@=-m1cU z->`A!uu*ybH~UHy(y00!m_!$N!gW6$`&*! z%Qq=o+@x$tld`2XdD8v24IAWQMp>are?3jgRyQdF4b|d1yoS%7{!&+GjMp%BY^*(Y z-&itsWGoRoJVvoYW3Mv5eTDh$%gk?2`F6?YWtc;|Ezhokp5k%Rb74|==CY=!UQWc>UD zsK3tKrMZVbmHHIL-7Xq2cXC?%J2@Y*`3Wv*kvk>Vu}$zvv@_q=^Y^0ZX9Iu!ocTQ0 z+&B4=(XB?s*AV!uh#nSQ5OG0xN2|K*87YHYcF4Zr6fR#O@c$#rySVsTdOJ!qlsiGg zOar)wzkKuwp_k=H+i1n;NjYO#ar7Mi{b`m@N&bBr%co~)7vr_(==rpA^bjEif5eS3 zo>R2)XeX`B@o&5~BV*sC@-W6fLA!?=;c{=KPjV$(N4+xu%OMj7znU>wqFuQMj1ALH z6Jz@Xo`;xr9%MRDnQ$m~PolKjJandQ7(-)2+vJ>oMJW zr;Oc@js^FN-fQH-T;wF+wc2CG*~dKCuA?V+gIfH%K_4=0Y+byOM(13&cp5F!yLFlM ziz&tbLTlg8eSD90?zVlbtm)%f9uIW!X>&*GFPO)Emktf1{KNeD39|QC?fsE{gQxm? zG*iWewWEQL6QYlRCVH4A;G67Wnpi%HyIs6bnI?LeCWaY*JxmkJnI?Af*vpwFdW0rG z2TBt?M{i|#4~cBEI?`sdFT?kFf;+&NFW~;VZ<{x77k#HEz=zfgaPsUV{Z`*cCg+I= zA3>7k+siE9PSLTk=jgt%XXyy@p~K9N4l(T?Wd3wu>~ZFekNLb2W8wVkdf|6?KdF^g zF~3v32mMfa=iK{SnBTQh+YtC4Vrs&=9`JG=)5>vPfBwg7_hnwYV;;lcF$^BV;4usy z!@&FQfX6U+j~P0D#pu-~bI&1o^AWzG>4WI|-zu4l^t`Me=L1~-eFK3`@l}*TI*k&yo=+{e&ZO2`;rC#h;x5()?`o&ST`6k0tCL#qO4H~@ z_(x{Z?lI^=unAahvu(4BZG%+q2jonDwsKhx_eh@M&&UV&eR3|)@hu!H+(4!U?`2)c zd^lzFLAfuG$Jy3KmYvACjF@S>UDtnaf;M7K_qWkTd}dv|zl630dCzbtkNgJE9a)Dr zckRBzI{9~w##w$?Im&hg|8?1J+Q@4+!Q~UI*FRWBKk#*;J?<$boAkr=J@k{Lhql^2 z&Z3E}ZS>$MmmTHb%luvXJd4{T4Q%Kuy3dUUHapjeQJw3=QQIf_YU8?pW7-QI7ye)N z-UPnQ;%FRR%XVU$Ktu?^oPC@qwv*V2?1a>$3AHTCw&F{XMa>gk3!>Qn(a9Q*ig zvcRU_jxhBwE~6~2qBCoBhQ~l3>)DaAM=)+6KFz@UK=yZ!1KFPpvX6ZM`Yp(P4#<7( z)wGuaT4<0xZGbTgY?r;mhe75igNl1d?8nA(uzb)ByQSXBVh82<Cwd6WP%00ya1W0I?N->{k>*xbT&OF z_pMU&HA=xGg7hJc{r?pKn*+SquIdAxy&UU&Ce4{!3|SN}JDtv~ zTm;`3GgSuPx#BlJ$5i@miSrN``K*fAYrxChCB~U-aVClO9@4jIJtn0+H24y@cJzb2 z2eOm9JBv-Ad1E{~Px7mfC7JB$lg3B4fzO}R z@4_)MpEV5RiSZG}nwxNZgmHz>pMayC!=BoOXS3E}{KQAe>pMkatxT>nsPFewvl@&Y z);mD3&j&ljVVJF-Pq26=GE=6{J`=}}{YQ#+$H3p-jWJ3J z-5qHr-WRdGdy9G(>Tta^3w#S1`=f_8o?XbxVTxfk=!&6ihW*)I{6}@)C)(?;>ju~( zB^XmHZCa|wmyYA1xj~B0m39PQr{eK-18jaD-Ul$d&_QxH323^4e5fnH23#h1XX(Yd z2$?FD_4qs8#jq@izc|;cV;;Iw;b}-Oh4#(@K4H2J?6KK;x9+!eM*X0U?{T*5#=aD1 zdyRI|v+mMTR!#c$GxqJIexAkZcFVpVXZwsCbZh4~QEu>ksaVT?7HJ-+rgMvs_7{b1o^DLZf;wRyuqVo1Wm2D6hzGwHcMH77 z4(T~hPBr|2-J{3*l3!&*Y4sYukvOvf=W`?0QUp)p`!r{!j!jpdItMlq?tTr9Y_@!N zvW`8hlYGx%%ZiW1V}=MjJcaY0kI{PaLssmvz~dygZMN2SYX`p*pEj~@Cu|TcesP{^ zS;}21=%**zXC%!%qTsosV8rjUL(JArz+liS~3nP7rnZ9W8nX826BnAt&FiwcuEqE znb4<;L3fmhG4Fsn=7q*6YeGs|Ny>PJ&(q;uoaH9HJ2TG2S+a?Dh44>Yop*g70(+g74i_|$PK4{6pdbXirBRQwheUOvYiu|edlq^ zxpOjW+d054+cSx^?a5*GJ$cNzrxbWs20S!U%;&*ji~~n3F2<%IPh?%*7h~NDs0%M= zTmQRE`a4%8#b@IfACK1h!hDDr#1mkq^n zz6O2b^QrAW20xAePLI1p9UoKE6-qyYjiwuU`qXjK`5tc^pJlq#6TF}ON-h7$?jZ2# zLp(zmo;ScV*i8#Yqq{AhiZ?l38BuO>`p$9E?-B7{sr>=;%L0rMoTGO$6|M^3T* z$p$$*GPH!o!3T#%^rb(RaE-64(C$P*PhJIuF(A~ zpXn~lBU&f3DHVtpY{E)ur=i_kM0+KxMZSZ>xVIPK3mM;6nNxa5C*gC9*XYomkH;S| zRG)Jq(DOTWPAG>xIGf->&L03@W&-f(il|D(&?YE`s*9VWPeR*zZ(+mw+`i} z3VDBo+HW%3tLno0k0sjgvbfZ%>E)~-j${9{v|~S}>*DD9O*1^Dp1mpM;1Y@*6*d^* zoW}T`%STmMA-?~-kfa5Dk!FRI-q*9kCPyHAeOcSjPgWH^is(C*Dd_!~yR^L2#D z4A;2Op1_!5?n~mDUAlNg3D04BagR59hx9?}I*%4^Q1^-oldw7VgU!(ZHb*Vk8`WTM zjJ7ADP}mzq`v)1W*P^YVXlxCfSCKKTQL#@&?xWg6vAOufMCQBcIM#8~0ILNV^xd1sI_{Nm?{3zs=lPT65z{42Edaw~ z^{%3_M!?;`;cCZ&8{}|{G;mrN+?R$n0m4*_0yDGl4&BVc2*dqbc!tR_=pUa0oT1Rm z40@do-(!9|YoB_!@ML!66uiq!r(-ATSUc!{jF;(Erc(YKw!>JhpTcG;+ZmRF_Z8wD zj-X2_B#&qI>crd@`lEa;Jz*E{7|==V;Xd@Gd7C8SlQG^I=9_%_t>9b*oA*QjTBkI@ao*f({v za@i5%1mfeis)>Z}`MBIWB>VltNpWCDFM@%jULO(`@>~Io-2##?1KHh z6u*G}7oM$0?On=aws}0Yl<#zL47DKJ29Rwtj5(GeNE>3}+_pxNZ+#m1&QayDDoJkj z#UtSMaJadn$}PZ%*#4QLz@Tq1Q-8T`rhXYi89RpO!h;N9o^vrqwf7{F!Cw7|Y-aCN z-QmIC zv-`3AdD~SBo3C9b&qw=v@EoxhJ+Y61&O}JFKPVADKPak!}B?X!}x4TsPP>yX4r9YeG_Qq@KTpV`USxT?6>%&g+f;u59tEN=I=hR*0%_JfIN2jt;e&=hH}`pTTft@74tijbu=GX$cFYpAK8tuN2jvA zdrxD7d$nsZxJJR(Ql}3gPOwS9ThJFTWVm;#qWA-`CNqr!Hk(p#Hd5U7>ST zc{z$G2iI|M?PofcgE6{E>ppEdSq_%*QJj~Nuz_K0tvXC+g~+}q=fdP3CdpqqH%QOt z(K3~rgv{t@4dSu*H}t9V)rc2yCf}EpY)7NL?HJdN=4-H*Cc&kb|4D%F>!aAiD!!_A z-NJET@a&cHabR$M+%R5QK>O)q(2X#20nd~S>UJ`~<*9H9orC3O3BKzWoKu49t62WO z3-j-n3B7F;>;Uu0=gf`w3G|x$;&ixio&wXqh{p`G^-~$$b$U1S(E&WKvsyp9H>Tq;uQPY^a_z!DzqXj~ z*)h`^D8d!fI&VesXX=@uiLxYb-iI{o*IDe1-KD@=IzL0doXswLDElUwUs*n43^k!V)D&c!DxlC#0DP5d*sV43i*C`CbuVmt$ za~SJEr&{Q_i0#{}uzf$2V++U0@0v(n>qyYJ`HTBYcIX}$?$sR{-m1H6c(d-#;h65= za9DT8a6orpxJ!5Yuvd56aJz1QQax7chDt{37rY+V^nWdeAZslSas7UbdgUt*cbd9-wWHU?c1CY(Y2Vi~|} z&H!d>1~4yYKyz;fcqE^9WGF8?Gr+kk1DJsfV6GSw=A!<8QCoBR5gzIP6SVtBDsM(_ z^FRjW@5un>$0Pd2BZdUbcA^i`c5xa#2Ba~YS#HXq_*=`pdCWU7k=5LUF-bYB=H4Cb zXfgOYKVl`^DlX9hTTWdJjf0gR;WiVSJnlL5{jX8OuKvxsJNsk0gZ*LM9sL2_f&MPt?fqWeZT;=KMC{m3U1G0@oHNa4 zxnj@3$TK`%KX!k~8Ceeu7iJwAo|<*nus-X~;YnEshx4-T7|zK$FwC-UAO07+ZTRn+ z7|G8lHg?~xk62>927LiJXM_89Wb7Nx*?1Yw**sZ-cj@vo!K-zL*?&G~!{=ms=W~fy;C#Oh*9q~gQv=KHD`h!- zc}yqHIK{mj?c^&L(wgSO#kkIfxb=+R1<(cXUdUGqwrT_9;pYkBdFKfKwgw*jXGp_5 zpNZH^JU12X+6gRLY|zAmT}yVajCKNeiWdOM_& zas_SP4{hELZQc)U-Vbfw4{hELZQc)U-VbdKzCl8+l&t$pb^skap-!9*9)Ck;jZz(x zWe(@zF+JV6F^L%M(eC>|JiGhVbLj?q*#NWg_4+-7>>P@vs~&OInfAU9m%)Dz7 zs~h0wqZw|R$Y#>{Xq?A0@0}#%4P{oIjmG)RV-k}2oO~`?k>)-gtaAaa#aCy<%K=t* z@t19bR6f6%hR=h*=as-`C%bFd#_k+$Vh4vCC^q)Mh`Zc~*BHaKe~@`8Uf?7Ho_}e8 z55^^wkq$NYVr&zL8l>G;ayFi4OWF+emXfrFN#g;HDaaT8J|5?H7*()pab7*fvR(;e ziL)#o*B3*@Cg_=a_DoEt{Z{p$6ZZD8;)!%l21f1{QM{(*3eK~=#?x54*f(80^=SMZ zIlj8A&M0)V(^yQ;PRwCg{%f>;VSusD zylpeo@o}*i;89vnu@~cdx`XMa=yCrU)TKz@s{{V_1AqI0zx}}9e&BCE@Hgr1HEg$b zYPT7*p33VmeF)cmaGmFu)ON}1tN4w)!u?r~#}j*)2dEDV7!f;%F-@3eq&NtSyGp+% z@igvz7_4RqdEE_pZc93Eax&8!iVBUudv`C=An)EhQN;Ag_6A!)?3d%`Tq6CS#Iq*w zyoq|qHKKzQPtmLUOT3-%{8_9O&DJ~E%}5u;rd>sK!59v?uB{j6yyAWfPJ8mXtwxY< zZOjEfvlV2ycaY(}5f_1x=E#eJU& z?H6b4!}y?B153Z}<2@c%!Z^O%z9NbPPsaJGij%K%y@avcK$q-iXR(pzZ$BC5vAmPS z`CN3axT2{0fbs;~qj4GYJO25%IdrcklnJs#GBq#=GRdYTc#8bsYk68ZK9NvQZDe!PmZg4Ok7Fpd~vi19vJRrhlaO;PTUMS zF$Ov@3_39YIKeI6EBr^_2G1d*?Lt(f)+N1iqq_y;t*ecqZjk1L9oI_D?}NQu-U= zu|l~Qg8p30vJEr!+jOU~z1PFIc0I3(f=z3gF2NoHA0Qd(%e-{C61C;l2E{=P=%wm9B06sx2_zBoF%J+fibz2>civruuP<9t>*0iLU^~9C7-o^VZ41R?o_m8l{;J?HzrRz;ANqPD z;{?Tf0h35C94Fl{PWr5I(r1s8K1ZaVAo|kYapdKAke92!guMLa*uN()?~ehWPF`La z1AclM_$SAJH>9Ee;W6Ng)4<;|20X@MrNZAb27Fl>_@9jdZ%hM!wX{Fx%lEA_|A+Lg(bA{?hw0(pVfu$( zj6RM_*i!}UTPp1Mar|=55%=!nJsxN?s`jFoXPhkT#8NSqoCITZ8O2$SP7B%2V9 za_~>9=7Ipsu^qD?{1OK|Ph-NM?r@6))mb*KbP1t=F_}=Ei zY&L;S+>LXCxgx%~3Viwp!J3*%XS!v>J8yA2^B8eoCF17i->lI{6kXoIcL2AiP`V$cR*?Orv!JGGbZRcqJU?K^wLUIxbA6m8Ki+TvY? z_lBV_j&ZCohR}QtOFJ%Q!?^STL;Lpt@w`YA$6d{&Z_e+n_9pA%y@@JdpgZolPl4^+MRNrT?a@NpI@O2!iSXUJ7~Zddm0g{vDrDi#H+93EvxGPhhz}7%fdd%K6opHg$}& z!ZFg$7$Z#?Bh4^ITIm>RWn-in$4FZ+Mq1SvX^Y3;=ec8~G5SlqSL3~*|3iNUf9U}D zOSgl+bQ}0fss7Q}IoGtoeh7@Ahuf(>uicxXQLSJ)c9^=wP^c`puJHh zuA;jd8SUr3w!i4H_N4hw9=FXjbKkO`C+=)X50`GN9&4`_p8x;UE{?yr5ASZD&kj%J z_W=x%-k%9N5qU)Ssg?3Gb_Q?ddNY^tyOGddI9_0 z=i@n*XJyklzqr5VY|v#mUUEI&3u8_;-SPS9DCdvqsn007vF~V0jGahBdLK()d@Qaj z*0Gv0obQFPeD+jY&pXUgOx={&xwRxX%IMt{l;~lheOHPWnaTq<<^T+S6G3Tyc+UDd`Hl zYkgZkzw3+I4ZiJ$v%qGE$0rzM|Hk&3DDH$lg;i6U!fxA}qu$ld+Z*S^Pa%6l*m;1D zbdI=#OTy?hdsfk}Cz#%9oa5G|w?7Xj+190L=Dd$wqD$&4xJHV1dm&C~=V!6H0jsZdR)=8fa$&Yz2)U zIA6}&tXikN>l68JNU>Shse8i)$gb4mS!m#kK)qOz{tA+r92f`WS(Dhlhm{kleobVz zBTSg|+-I~$34h}m6srA@H11o}ak)P2xLgV8NDIk}poQ!AAM{TG@{leVm-=#8Cyh-= z7t({}0{@|%ZM!h<6v&H^oIWhWSNw7OAcSCN>IMnvU~bV3UO&~X1{^%zP_q| zX5qKlO4|3gcUbnf9I>AFoVpG*a@_&b*Q)3GZR=kJu)9D$&yVA|F%bivDLZq&_RPVA zeJR^#Dz#6q4%=JyKZD-J66aXr{<4#&;QD2bs?V74J1UAfulX9uhhyx+6X(3KRNcq# zgiEu=-aE+ft~2c#nsJo4BqOfjiL*q`5q%EzCbrvg09wj!6Fk)ybGc2X5!X4j@5LIu zj^~lG&eJ}K^RtWP9VRnMb9LHrXFK?0P(HN{zh^D6zMVSvfaPKyMVy6Nz~uc>h%d3` znJN=lzp-(TzV@r~w~E&%Nc-6(KN9Pd{QR5C`Z;}rV!hHpWAGYPugN<*bCcvEXAEB` zZ;Z6j?nc72|F8RyMSxT|FNPt(X};{2e5t%g1( z#$=oUpOJA@3Hyzo^{TPmb{-~Q0PiMK(yrrjf2@k;Efc;3rp*#}MO6v?%hUOoHlN9{ zK0UrV#>a!i`Uq*Yy`~dud5L?BucEVcq|U=w)Z}!2UpuxR_w#svkav?weE1vF z_<2FSBr_N*R8)xf9JmLu41|;TKA=7cx>K)=IE#C%aRzaG8c#jTE;;>=YI?e{=n#xW zcfnY6CyY4ylhk!?yf4Yz zH;L5{?xLL$Mt6aYfqT-ZxV3Ws7SS+?+VDtUQK1*cX0vXNew&c@Uflz6yu&*JeQ7Y` zb}G{MYHX17I)Lw)${AHhyfsex%WC@gx|sW2Pwt|4eX?7%eHG7u)k=_If(qs;Pms-dKrJQ2kg`v2B9)JhN8j4 z4Chf%SGKeLmlGWWuXFuN>oGg}%b`t?AB@_4sKmhb?>z(X;~2$tzx!5x-^)QdSL~xp za~Dwl-fF7H38atYn827k_l}=mJNmg+c-Gw~@xdvwzQ=^!lxbd_;MKs6gdc%H zd_Io%6!SGxnXm97Ils>5CLo>OBmUBqd9T#`xE_|sKa_F)sE{&D}Sw+3uynx&@QA+ zQEj)&fwnt=rbuxEJ6N(Z=dO~foI_-{t8?jNxw|Od>Oj5Iz{?-e%=%Vu)|?UgNI-}YW=o@o*UZEm~R*EgeZl+S){kXdo%5`Q<%p% ziRKsv!KU73D9y#W4RbH*fa=0*ux)$*+y z5sqX&N77`>xwd3&4quzhR^v&N+gSP{`HW3K_=K!llKjnV!Q*R4ZVwM7I~>{=_}p!ZtZ3V<&cCoKDgn;H%ZKZlM1|^%?)P=agPDz}WZtaSo(N--z@N z6jk?<2k8Rq7&wT!7}J$j62bF;H1QryfOhC0)&FNg21ix|UF zc6ci8(UdT_Uv)906+oLz#xiWEkK3ot(O=Biw27n#bWAz<#(1saaroeSJhQWq)v2^h z0nA0VTBfC4?n|v@Zg2qn#-s5ahWFz*59@*7y(c0qGi(KbdrhMQ3r7U`?AK8PQg zigajcd@t^vx|#NhWM7ET*rqGt_nYt@%hd^5Xb#ARz9s+tpy0Rs{XiVoNhc8=#5Ymk z$rb#OaQDUW9uGX*nE$>zj`u@MFeJAb_jA!VEJ#U9tig>wpHOr|FSJK5#{aMq-~--; zm@Mamd^}N7-tVbqGw9AuJINRLWv6k!4CvXpUq^efRX@I6mnG&|Fg|2<;S}6wN_~p2 zF^%R=F?G!e=^6_*0jFdHH@?lqZFQo5r{sZ+CGi02C+*PjY%DCp0A-}xOOL)8&KJwF ziVE$byfE|wFSH5xS8V!je#W$W@E@eV@mzk4(Rg4){W2}Ps1V!!+F>4t4T@6ED=Y1+ zRK$Luyp^)O@NNo@_k&RW0KW^K-;s#=6XORyj-Nn@ndUZmY z$Jk4D&Up-NB;AyWthma;ij_+sZHKW}$zesxcOmT}qUkumTU_O1Bk|(-9(gk*-7gEe zkw!_g9_=js>+H+&0P`aM^&}(L?JBB9TkuFJ-A!H9i}R5*j?O4N0`F@L$3Q-2D-S`w zH`pZbMRcsARLAO}%)K{H#Q4|h*CEdvltc7ReICw zG#+CRkMA&IfBlGEVq{s{$|kc*jq%AljqIcCM(n@5-=gk*#GpH8B0CXi&11Ot8~V5& z?b1hR-W=cQU>vrwi3XF1Q`Cc=!G6xyA4ASb zPF8&ZzOS6=jN52lUZ)JPWAdzWZ!y!&D4wIoE0~Q#nC~-evz_gX>vg%Nk#1a6M(C}C zeja;Gq6x?9{k_o6y16)?gmXznJ6~rFfd5RC2|ANvdLP;lbnbd7#!eUa6+L!1$!Fzp z-F)6r`m;q<)#{q>BpCm)S$obLXdRvK^W*XC;u$#qzQ?1(^4~_^Wxx#Ma=VV}|Iz1b z#~v5PXd|!-C}wlubv|Z;?S%AZF`J=U#QqlTJPGf%f%aR*WS#igGnt(sqvZ?O9Xf93 z^{Vz1#)<3Iac8{qXtZO|4r3?S!L!)5QuN=@rvM%<(6ingE??XFt3h9~>>B6~+u-;1 zD{Ax@Tjpk`GauT@#P{RDGMQ3{{P!5;c+!h-p!Z5){Q4k%VNNw@D($!QtLEY48ART5?vU2bo6gEK}GZ~HrlK^g#&Tt~6vFzLmmZLLFhvy>AnxCHC z1ojKsN{O=-M%P(TzD{TO3f*7sHzej)tcFxv$Kvt~yRq=e{7aMakCzX9VjZ2?mM(Vl z(C}h**YH?(fXV(^2)1m2W*r**X32pcf zDANo~Kh41B?{~l;da}WaYlzvW7*hTIpT^CGlbO2=%fPd|diD64-z{b<;P+|C`NbmT z#~>%Y)RJ|qmu%<;ai@AbKE=TAb;-ew2zE#>t^#jlP$GW3S8_)TgI17m7oNRc7eAbf;FRJ&*Vx4ogQJsM=E|x9k zhRnQg1HX<^p0f-{!%Te}o2g#`but^j3@!J^+ovEu?jxM)zDizx)+vU7w)`yUGrCg@ z$Fn!4WU;A+Y~F_YWAPcZhn2>|Nhcd_5Oq2b@12J4?-Y9JRe(o(O~+>79UmfonE#o~ z>uW6ZehvC~hx{`AH(Cw}Es<;m&4H|R@Tv!0pLJ-58#lm+EqjVyY9 z$rYwemMg3uH}~74D~8s7#rtr6OXTg&pGfp6+Umj4O;kvc>I<>CVzb5+w{le^mMT4 zKHB`5y#Igeqb>jAC5(Okb;e$R&pq(D3O-xlv+CP{byg_`NC5_oYQn?{{35T`}V~0yWhR+ z%m)U%`n%5jMA?5{!}<4o`l{*Bj&D8l;%R?;>y_?h2cP-u(TkqmzI;#Mq{BCC@Luq_ z`-?w4?)z@*+N`NB1SWVqOD6y0FURM7|1l-_wQuPCO>ddnpN*W~IrQXP*^BF+$!YxJ zqT`?1aIj$CKW;d9c3{u#HNSiO7cW(Re&5Y+2A;3%S^JvhiQ|9w@~S0I{`_X+3&o4r ztIK+qJ@?o&*U<+Kes)LEjE4>^zv{|+pP0Pw{=2WaTUVO5Gk5*%FHCyG@cwbPU9vSa z@5H9Al|Mhz^~)vY9d{0xUfww2{Fk!sQ=Zy0TmS5bmtJ(+`CmDB=Y)N4J@C`{&)ogq z(Bl&~FZi5I?zeN(|rk8eHxmBr`h+HNxGO7!~U4qdEFdVJ==t`!F^3Mu)| zblmgPw_LwH;qzC&vFGs@W=-F7bpIVUJoo4+OAf5M@c29Cer@gjcij@W_pq}4?ho!f z@W9oR-ncXS>Zfjtom2npABHzQ^^=o}U&`4&?d9l{<2-Nf_?q{MbId)jx3YrUu9^6)+RG<@^wi$GOS(SEI_ubx3I25}+<*I3r?2ueH6_dBcZ& z!HO-1{B^qyxPEoo_Ky1op9;-f_(qrg%1x7gon3$2FYcM9n?A2Nx9!l^?tQrQxchJ4 zz50$hIp-Z%dwu-5BNa~^J@~zAUMM^B)>qf;KjQsS@h6@?{dn(rJq4F{>u#Ko|KqPO zJmHTQbxw?&w1VYsTl&D2Q!lvtja%p3_RXr(@0|3bzNdB{f9Tn_@A~lNtwpcBblfvf zJ$-S_8_#_F_XDqV1-HNWmETM|bm5xfd;a?SP5VQe>hCIiXLa7r@OhKt|Mj&A9cz!v zIx&8Yuit;G`|nT3H@GZM1g33%qhRpQPaXf9b9+w9kptQ1xQaWk|J$_oqs{ex>r0!0 z=Po_($y;Au{ks=Bj(e^8qpv;xRmZLO-T3e|zj*aKPuyPre*B>Ej8E>r|GP)-{V(I? z2OQV!y~B{Z@aVmlPk8P(vsS$7e4z7%8FMe_IB@q;*F(C~yVhMXCp7!3hmO1BXMK|% zJpHxY)!+Y6SI*d_Cr+91qe?^FEh`rK9*8yU`sGhn4?le<@LzAg^zHZm_V)|*d0Cgw zKW+NHb9m!|+WXs<-typm zEBl`OY4DHl{$uN7e|cehMS*hJl)~)mH_h!h=v-|1)%`U$zi^GM|HFTF{Nan|V~^+5 zeBUw6_0zDDbK}XCCBInM^xKDD`^E>){i|!|@2|Sx=bzqtk$sZ+hv%Qw{!a$t$4|A-d1;Zi<%9JbyW?9gy@Flzqr0YDcgs_T2Os!&;p@LFY{-B5 zYpZ9!{f$8D-@f(jK*7H4cNAWH*$?NwdHpAg4+K(YR@(cs%NFfD zaC`02->g~ge{FO7r1#H^%=_oL-~V0Cqd)!2w6|^?P%iw%fy$wWS2s02x8)mMzdxhv z_)oun!Q2zxz2vWFJapx=vwyaCf7Q0zF0b40#0AcVS5~>p|F}4O!slP<|J#Ije)7!J zhkt(C^uc>}8@E6D&6e|?UAfl!=92TuK0a&nWcIgvT4p}=;|)vi|1>AG=XXU{c*a5Oze@?17_??}PRII+`&8cS}+4W8RyElI0k7wBT{q~$qy+2!C_~DM|lK(oE zU%&sQGWV5tn2-O*WgVrjo%fTc4Xt+IR~ z>#y0afB&p!W^`Zu@q~s4uJM-~{Y8`RFV%N_eu8iJ%X138I8Zz9`5(C2hW>PV_>#xZ z{mOgSEnD=P?Xh1j+}!`xN$YO<-qy;8Z(ViD>$6|E+&lU2cbeLN_`+Pv?f*LNkaglm zKMG8L_OtBfd!H=s`srn7W-QeS@jR>TsG`;2C~5)xb{^ zeB*Py#SYK4tKqpB9?hl}#bIi0HNkHOd|GN-?RJ2z#pn9gCVbyY&u!Kw`~}Ze{OvT^ z%}&S;&&%kywZ6@yKz^mhWUpzf1swJ8-d=Bkq!!F*vg4=OLbNpFb6X9)Ux8(tEiDdf zYl~uaGyxJS$BgeAnp^D_!fQ6!omPuoKseZH@QO`s4yWDJWF&Qjf0-;CTk0;X~5@36)Tpzx)R^D)Hj)GEe=et#ovIcw$*{@H8t?D zGy(a5YZX1$Ticr9o1U$!@f*v7nzkVPQhc^IBTs6e-Zc$v*fgvLXsl^%vMvXDYg+Ny z0j!~_HdySdE%mL-iE+rJnpUS{g^Ae6YF6Oyw&fOQg6Nv%@Ufd#TbuA3KUSyJ(V$pc zYOT=1t!4}S@3h$Ab*mj{wqkkqwib(3sl|#oOikD%tOn_7YpOTdt-P#y{B3UpLX;nV*g(H6_SROcIx{!p?-mnOotf!lvnb0g_FCYPc{%=G z)of}}o0K&IZ6FEQri!VKi>KXUYpZFpnh772ZEi48J2`9VxuwO@q#`gkSetMr-rR&~ zT<***_-uy`0j;lTXY)#gv)XJHyHhK8W*dB3&8-flw9x|X*-}3%f!~a2O|8u}yuRjE z{D6ppXf$G7TcOk7`+D(QrZ^icO0A{2)oeFGe^G0rwANt~!eTvITN@KxfZvVy4!Pj4 zm^2AMmD8lyso$CH_}dBCORURVt#-nN?O|_)l1!`t(|H$zZ}_aTp~%8Fd{$e`4I0jx zL0)SuEzKr-Bddk7Ypo!D3W$N3*Ryu16-3Ty<po z4&U%xzsd$858v>CikX_0QB9A1il+tEE5AE-m#p)U{-QH@^@UaePtFtbp`qVAO=N4-H zI(SoOH?^28_>CV+3or_3;+?O)PJL%X+ocdLltddSgWvXZbg0Gewzb97RI6!^2B4|| z7z*NUQA(F%PXSpnTb=O631rOznB^vfX{l|qo2ZX8w9xN*r4jza-;MZtg+>hEcUubx z@hbQRooBYtODp6iy~yyJo?B%@S|N`W+P{o2G$;30Ot(`yPVzJBGJF;|fxlLV-DCm& zqYkz@O-;x+E7X4}j5^p=mNw&ai_&abWkESuYO!CxKt7+%mYyx27qX=bx=pY6-78s)dtVyBi}3Un`RZD_%+r9cmC zYQo?4S|n^K^pQr>YExqanG&oKbVQ@2Wfk(N5%R&HP~S{F-h!-w-*#(_iR*|)_`eYb zZc~|7_t`A1wkAu7Bbljnm`_!tTkj8HQDJI1X(fJO*IO(T?5n$D~%1> zWCgwH1XIOnp|QQmiXUe~8(CQJ474`2t+c?1*k(r>LGGGOW;CH#b1OYtYEg^vaiOji z>><0ds;#~iT4s52{hJ#RzSdL^#u0Y>=6d|yWLg1bHm~5%tAze(UPZrat;;RcH=38z zZ)%I?CVF-vV6zjSxp-T+NHc3QzOy?TOifLiF3Fl3=sj3()@5zb-p$MKcN^$5UfE{5 z{B6Zyg*8)MSG78w7Pbn@v8=S>_}C2NEc7Hh?__04ou$?SEoG_YUE6_V)FBPl+7+f% z2@0B9n`&E^r%DC9uf?<$6X7<~GZ?CZ4=wcD=>Xk}HefU1vA3E5xEX0~U5%QT*Jm~I z&4hyO78^dJZs!EHG$s93&<1X5;`~P$ZLzEX zo3)9zH|96V+*(K8~4o6KGycx8kQBhdO{0&qz-_J|o5O4MerH+Ur`I8r9C+ zQb+Ijpwo<&TZ<{F9c`4p0(E=~@T|3&)DC>ZxMgbOjspDI8u51%>2uo(dWInvT3>5A zmVqs4ZnIe}wan%qnC4Y>lT;n>8@On~Z~WN6BfuJ~Lprn7<9n(xjVm_zAMCF-dWIU> zzX(Sf-|HHIM;&qs~vdaFj+}y!*`1l%=9J; zx5?2@;O`o(PN##0xfaWE9BNpj3g6U*=2Vke{suPMg>%!4GTB7-fvs7lg8_raFae;t z;3GRR2mY259&+8-3I{&(=EpX65RO*G+1kwU+u*&~iY#UhC#JR4T1mz6e&c}u9hMdg zveSX|T2`5%b|lRXEC(qyDNUBv7Lr3p6TXA76&itX*5fty-D0gZao#vvYfO;E>7@5aEI5&hxviyv+6@O9Cy?HGz|1ZCyZ&(->EOQ0j+I~=)zkVDo?>3;<=^Sio*-n z!xl9S&6QfzdG$5wJ3asb91dVf@1R41&Qw6qnpQzZEluF+GZ-C6g|$Jw+E&+CWSh0E zMmx0yEa^739B76PU|9_v8yT}4XjyIruf2ua;LBU^Hwd=cCCU`xx3lH-Bh%XEI_6S7 z=u0b1jnbWg=cXnrXJB0$FrM@QNXH7406R|aGyq?qKY(nkvNV(Jxe92JRtNUbRc+Yc zxKFYgs9SAqt})fDpuVvhA3qIuzGNmp|Zg2YiYr)ZOh00(eiDv53zf^vC?J02HjiTcz6- z*`T<*u5ip3QF_8kX()^cp$u05dV@E#DTw7nd{LleL9JO2hyWu{7dQXfhxIu3Z?`?o(;e;w+~q1 zQ+lF4Xl+km14E?l5P&Nl1W}?fV9H!5E!GnWD!xbrn2L-Axb*<9xMDG1cQ~f_JCs)^Nlh zjDgq$W4>T4io)aoRoskNqcJbGFv4z%_+vh{0{>SMNP-(9uI}|(JoJVr!G?}%umm?k zYalL?tQ5e4eC!oVHo5{mKBY7WnZhm)WOqeEJs=<@OG-#r2RC*Sj!wZh4v+Gmicr$V z;Um6{*qtb!6h;MKj_7HObw@h`zKy;B6SN9p0R}}w(7(JscTZ=hKiH{s`=U`-CkU!P zw$bN_g(3y{)Tv801r&)y`FaTnA`u$Z;tPj1q2RcJfT9~XuXKmJzC|R5W>d3Lisi*z z!B}96;@afe;G0E4X>%w_DP=8>x;Em=%0)N}>BJPoz!(Cj(4NRZFiJGw^M!e*;U#*Y zdzEuqyi|^hV+lhm`=cJhC7ydw!U&5GS|Ad{*7SOzgG7O$9v{ga;8e;L(b)kX{O|>N zs{nsPpprrn!YQ5!->8`smnY^Y(i6Z+DF~Y{(g8vO_3#G*3Rh&lD9K4j#MO!4wZ1SA z1+TqxmA0r)!S}H)Ahv5Ri^QTM(&3#t+$G zYjZNJYjYB8<=G1X+PL7W2oC)zpu%!R4yr4%1-fy!KQ>Ak0ZpDj2;^`4EDSk9{0K!n zIB0bEH-kEj@OB58^m~P5l8{yzE9X{JxD@Ohr9kdEWlBXQe5wH9f-+@3yjlRyXD^sF zYGyajj3fZy+_NEf#puwTBcMg86=RfKUI9apufx?7h|PjN=n8_C=!u1}|9V^j=q_F# zNCvbOS5$6L*^1;tw|GeAM>n8?yaMk3kDPI>=iejcglIx&lVWRF^`G+Q%TtIn^41%x z?f$1w>+W2ihSnqsYv$FDP2>M$fr0wTu9R7O{9j#L#=t^|xP*SU;&U_>>G6QE$p_R$ zicu-G);Juq&}4&R2u8sdAh%(j&tyx$f@dT_O*VjWN27i(;I9|@9dcT0d9}-gISZyM zu5+Qej7F;~8Vz~;IC5bdKzA zFhdn)I0rMFLu0U!24egVr36c;tXK#<>WQrH_C(1@mF)oUB4nF+qUcKyAERNPCo0+s z#75eof)SLe%Gn}<*yN9O`GYDl@GD#a-z;EAxtsU{yef5(JXDqf+h?JyZlaV;es8P` zc~Mqr#PkKmg8Vh*916@dO$!O25DdOM=)Me*xN&w2lE;Vok^&?!u#Q}DNNm^#3eSELUb z+Z^5$k+$n*;g^88c7s*z-vpj>6s$|TD+rzrnwC`y*3IR4Dn{mkf6@u<0b?CX@ZuwfhF|9^=l6h@iZcnCx7`V1#5*%Md~TZTaD%?~lI)Ss6d<(AX24PP}wMw8U6AHy}r!} zzakcaJ`TwO6a~UWq7IU_aQ>{hG{}{!(nYOJwo?q8dzJ# z+bw1$Vw*wSDgZqWn4BxXUJ_q*2&E~6NGMQ{4~}GyD?qM)PZ(4Z%6=*o)URs`vw#pm*L%^C+^w5!|KokUNx3&uS#iG1BCaj5o@&uQrrXu4gVWS#`K zDDY0LQxv>BPoM|rv^LmDh8;CHknntpz#H{n;9FB!wqRXaN_#x6V9e{^h%{Ts!Ja4k z2WNo`XM%z*=ruGI8QTJe);v<6q2N3y0_>H}us?)zI+DhEo3&L5`-3#!gDm%O~3vP+#Eg)ZkpFyFXsm77thD-186)N z!@@B@5!^z0!0V09i-0_C^r29bZVbm1Or|Nsg8T#pG9Q(xEQYLQJm$hy1}9 zl^yZn+{?V4u$R7pWU!^9gj~Xre(||di%^pnb0jc?5fU6D5ecs|jAv46xy+@CC?bz+ z=5t8gBk75XnL!R}Oczyrq(0@a{}~P0Z+Kg8&T_lzeO_6LE|(NpM^%&@F$x8oX$vp<8&w47pS@E2jg>2VOPXObId+< z4wBqKO*ML`>%!>nigYR!i{uN%@8z#56R-F%w#gU98Oxri;5!h5MX#{f6#l*-Uj%ophjrh||J4k=?Gx}L}uKGhDXUhcl&U|R<}K^Fsr zBzNBYN-b45LP({A?Chc`Ud3c_l((8|uon1eHaBaD26P~>U^CPTs{>wmJl$w45I2>@ zP&RShR&j0y|K$80D9xvsVYm|(mnd?S;@GCB z&$AwQi~6BnuGis9?#LrwB?KsS_xJ^~ z_PL@x5g*l^kMr1oa;S7RT5U=Sq*97+%lV+{#R&_PpIKwf<`Xe!AxHcktZ!{36b1`j zv=872yF43wz;*C&RyZtXlnsG?%ryd^E6gNXRIVKzpp;>-qS=L&DpsK0ACNDhyL3VC zxqut9(H`goK5umNV$k0w`Nri7#%-=>ir?S0NiJ@{_#^Nmf&V?U!Px9eU`?!;{HN4GakW-k2|Y zBD^OWJRtMQ_3iVWbf1n>&837(bDAwa4_Uxc~o(fDdpuj@43X0pRWak)EEdSCBskBZA%=^ z{571YtypRJUdO4!RLD{8jz&3TjWa)g4g8u%leSy^_~`O>g*@vNc;s;xiIUt(v&oD_ z(G=_w_>m9B3y4rp0IX>~4+}5VHBOPUOc|l10a;LKK~%wTB;@u*m$c+3=3@CP^iU{2 zIy{1zkk7^Q@%lkF7&dWY(ceujjXF0(OiwgSkgUG)FwZQwGInkOq|M&Nvv-BMF|RhW zoV&*)6^q*!+vEd#LjFcfQJSV}LNro9mNey4APNpSw3H880*yi(6Xf`-3X|X|$fTbd zJgSjRoKphF09VLef&UfM{}t5#5rWF))Wggn7;S<*|0}2eE2sY>8%uc2M3NbkHo2mIh@F$BQeDv;xh9U#*RyQ(SIvmQ^1r2m&6$5K*yW4G@5})D?(^lnp_Q z7j;FI>3rU1I(QgzlIOn%FQp<{hW54~nbnGCvN2R2NMZ&hH4j(w=hB)g_Abhk5-TQq z8`{+JS<^;o*2cAEfE5oTM`v`dns>cFxL&O5j)#LoC1xO?-X@$yL-$$>z?X+PZ#YP$ z1ffME(kAX%wDwIaN*ek{tV^jB(=uJ@`8|GLY}O(L+*N-!sUf-c71%=aAhFHMqgQ@zL=IWxcP*?@iGFK{TF$`6dS1c$~qjd4X$OB#>J538G zvJ>MI&Na$iB7B8r5G!W!xl`b?;8&DrL64t0Dby+yK}MrW0uK5;ihwUuO5L+?3W{9& zC{HZNUx5yN5PN-Rv`hp?b6g@HU*}WE%@(h4f|rbz>B?5`LC_tMwyTg2<64&H7BQ=~2 z;7S0>1I{P7wRn5>9o@a;k5d9-OL-~|&7fEOuR z49XhUR`=VlGWwJ60Gvq1TT~I=HqU!10HxbAp|# zB=RY1)EL$>#Wl~pj?e#MI@zsYeECBZ@AU8BS0iI_Z0QM8YbEqtav#IUGBt2Os@p`z z6D|F3^(@VVGo_Uk9J9eV>kh{f{Q(z5X-yCDN~-3L(JjgppDNFwaJVcp z?y7LbwI1zImaxmnB$P@`q!D~ikjBSUc=4Lz&XO}H%v>gMpqVQWB$bzB{-((%%+l1d zwWfBu?37n{3M{pbv>@e^Gx#IC2w*iXx@oO@;Z)%IksGJD!$c3?4w0Y=F{$I18d;d^Nl7b<9xgtD;tycf`b-^aFK$>eRD{NuTadI zO+FM#z}MG(iq9XT2pEhe$Nd*5lv(7x zYD$l80Uv!cj2er$eZCkSRnVlkjI$a4)`21-KL=b`a(Cf{i(UXDgIjr6$JR|@7kd{)+Q zB0qiCD}m0nie;tBI_dvIHE0%`npPU^Lp(&CQ5{d|}lAccCBoHPdd`(WNHU zY@ebauMq*TT&W>9=g}&@U#^@hXh(~D^q7E70#p)UB2JcU$ZnTM%ey403iaUPw{|K4 z%ur94FUom|VKXD96w<6QDs$(~1-3dttW;%-Wl(?uBEiNKw2-4L#~v;ayfu&t%p@#Q z=|7GjjvK9Lqt;?%g~oN^b|Vi%lZL4VEBdu2vU4-d!!~)Nqw#Jye_@F1oxFvTTaX_SjZnur$VuD}?6L>l*jc_L`F zL`S8|;{w9~{WIb9_{BmM5GIl+zm_tA@;@XD{&3^~Bc7D+X!NNtv}cYJroPism3TRl zE*|BWO5Ui1Au!UH&c>6Dt(){81vK)|A0-My4EPjsMlP|Z7C{q1-LoK1nFA6P zCs_KjVU$wi5+1-(v4pbE(&AY!ZP0}MGdiw>!K##&S1dvPVuW=H_5|)k5P`%E!j-i>T|N*PEP>l4>GA^a z{GGv2#JAq<2}YR+r%+1ki9xd#DdsMpX9HEl4bCi93UT2a7cMQ^Z3bFlbh2&^G=}`8xcOZrUG< z97mtT?eltl7`C|4?}4`O2ZR^(hR;caPnp$562m;tk zHeZCM^1z+k+GKZ7ECJzK4_0)HhlMdAtMy9aT|zYF?s2TWhy<85632Qq!Z=w@Q!vUv zWDL5R3&>r8O|C7t{ka3t%e|(wS3}$EWlE)*h$0?vg~KRxe6P<4S`uAmOj^=+7E#|s zb%|%`YO3)^{*Tv@@6cH9i-eQwBzA6~+)|J-4Me5sYZ3LhRd-7Ci$#!&)?(1d5ovO} z0=gxd*cC5YJ=}*tqQwNQibr+;RXZkJ)?~{C=hu6}Qs&b5O0+|o>JZu#>z_x^X_{5QP^2u-nqY{ab#-oFdp+fz>9&xYdp{0bMaH3Z#<3LME zg$R#IX|Xk|0>!pz7H$CQ0Gk~7h7(UC_C32WMhp|@GEldhMuWpN3D+5L;X;7~9RVxS zB{;_9yAV*sluH{}zUJvTVWQ~^c6^s`&MBxBodYjc8T^=VPXHRKObMbO`(fk&CAdDk zNr4B~W_TzQ6KF>HP*JA11Fql(a4|Z%y*}s!;6g#7z_dOPmN@t$VNu_9bmJq2({JW8 zQZY4&|KvINbAh%_3yh=J3B_T7vAOF4)qMHCs+PD1O0LOJKk0}n@;Bdv?~7oFq*mW* z-veT(R3dNv?!n_@wadB)BpsUZ{bwxX-`a=kAH1 z0uTZ>PsBPVlEnIEcvA#t5HTz|p)dK8MNcdY%0?uDr@&$%U#c9(JYn!TKy?N}Fo<@5 z?+VT@))`>eYjtokpeNKFhROx``W?a|@9+m84hLLYKq$ZpfWcbLLM~ktsuxYbuh*R6 zF=h_XiIH%~H?kkXYXzznjHRmsBqr4Xfz#Ch;le)hrV_B7svC^id^9&h`^SPkIMs@I zVn{+#9T3#xf|^izR|u#FO>FXlouc5ca^RtKokJA1O3Z>%x&^&Fk3b540&gIYnqSb6 z%6AhCROuL~!Y0u>8Z={@d5|5q!Y8(sQn!DJctag% zBR`V|6s)#y)jF+oRucHn>v2Oy%(ot=NvLn4haB(+Hz+(o-Fs0I)ee0;FUA~#ZGgh- z75EeRxlN$Sj=_)!4I@y%J4==?acJoq9|w=6CCOgT2X8EU#0akrl>ZNTZyy)eeccIP zFc~w5G{hl^(varH1`9bL4HC8q#x@ejMlq6zge(%{h?fC@&C7UZkVXzkNJ3(qkc2cO zQDW?pgt$sdw`y10Ra?5Ht+uP}(pFDb+ofH)Ra~0J=^E|J?GrHcZL@^ z?f&t6K8t-DZay?c!2yp9DO$s|j=k8OBUR@ZoB8-(}#MO*I6 z%2oZWdHzQCXao0T|6$i;{foFm!x{I23%IsEl#u0!Nz97t93Ts#}E^ zJ?KWec#lDfAm;B<&eHc4gJqEID34QhX{qV%?v&M+c&xu5oZcsL6Fpo*r}E&Mk|(>O z-WI6ab=r1DIT2284k3gZ7<%AVcDtD4M%@P^9{W&QUX^jg45{QYOW-|^r9a<;b}A~# z9SjFcQ>I8xGr_9mY5_0(f{psC*DQK&c~xXrwL6m7E@!at$1&8v08d&CbaGS_^n_(P zk-quCy$d;Fh2d0;+ZV$liGqUgJ|;$nwe-foNTMg<+x5yDi&r{WouW_>_8dfYlD56m z9qKuiw!+RS9g#%fOa|LTN#B*4E7vnzr@91`RR7XM%h9?)73ND_5A3`{?U`e?lV2| zR?=vXJg+pGOby3IJNtVRL!+JDgKnKn03Ul+SB=fhSR%crvZv)pqg%cweQ!_e=djGjf}!0WaF1O|hMR%mJ6DEU_pE=?Es&@|r`$RYpcAp<13g1%0=w8A zc0G@OPWJPk;l~P4x`R5kfh|cHxaz^iqeoigxe(NX?Q&K`7h@k1>!}p1=>%C8LH&6) zIXkj;v{Iu3$N23C1~TfsN78`KqGv=l`T6o52EzmW-KVqT6pd{dfs7EyzG}}Yv}~2V z{TOvK9F$?Wkd}%6!MmyYX56s@2V5PUiMiZr^|f>loI1X2pue}r+cRcdnvD8#ZeSi21VM&&h8xrh??hun^73O@+Ngx-cDqD9e6|07Qr|Ikq6}*Dc>H;B+2T- zA9IE{vDZslvT^|ZOpzKH4$zWq8PPuil=acLP9`kN79y+?8R~LDkupn(%>+bDO zx?J(ytIMJVfrBkH;%aV-Y}y}A#Ig-#lZ|cT&ci*@My{vC^Py;P`qne6_FeCJA=~i5 zwXQ>HU!YUAsP1;FB5ov7`+-Ppb%PtJ!ha7&x~q0obw+mkj&k=4shjLWr=zLqEh4iM z%RHDMbq(`*$&*I8R=r`i$d>;b$ryF-|B8&UsBV@qY?Dw&k-&|tCc*W`b<;WF#BDD~ z`fPVsB`@Uios}rk|Dg5;>659LEnxoCa`@nrfebJQhLf>VbVuLj#2}SVbGrS5oR=s0 zsAwghRdAseuuDsBZ@<2isV=B}eMNIad#Y?U9jB{%P%pJ6oKX2{x z6Y0IvR!TV^K47DVJ+jzc_2?m4c0TmP6Ktz`PI4wVB=379>`q+Ou9`~TFywt@_|G;T zth^1u#+?%?v1Y?5`Z1!L#CrQp21JGj}Ioe82OKI|0G64S~0xCm;L(aYOs&9 z{krrsqGDoCnn_zJqcLqc4+lsD8yZ}?QE zUAx5o2tp%=U3780N30Bu3=DWr{YtZj8iRpu0u$#a(!(xYukTJU6uLB>8DAdu5_w<= zit|i=fFyn4z;J?RyZSKQ)71733Q3g<+zEm2I!TqCL^)~7V>NObxKB2AI=kQv4@fxj z{+iq&mLmpT$Vv_vF?<*t8Prpx>GPiQW?Q=K@$`##?ONAXYZ23(@*J~+x=;0;ErmE56wgtL(D9v-JUt>Xy9YMT^lou_*8k=Qo+ z6X)T_vjkw7j9=sS5Yd6O9M9^PQ^hgdWDK{i~j^^EFAWvijWeNca3)E28lsCMtt%lsS%cJsL!Nn4H}T935s zYsh+K(9VzrcFu<5GAT5J^p$N?`Kns?$%pyyBH!`p^bXK>Y6~fj2S(-nLtJUsr)FSx zS1oE~+;%M4%F-n%8tPbiSAV6i&~@5duHl*)K~Bnqr@M2&djlyw z_L7}Z81#49(oFYo4_{O0*L@7JhYke&k>6(97Hj6oN;x4}>sD5k?>X9f2=y(J+OxM@ z-#T6MIL~(Efrecl>fGzyw(&G|mah+{NT#D_L)V40kBEgT>F0Z-`x!W05XPV>e!AAJ z8%d@fdximc7Qf^E?`S|CP0Q1vfHn6~x3!Ir=E<9^>&6l4VK@rS!*4({>bdEyoR;%` zn_1hwi9OGUAI2W@G@0t{?;Sp#crnmN$yqOv%iXo$!&zx{w~jxM;*Ys?RO0i%tyJXsABcsEn$xL z_a>aI@KR=-doa8ruB+M^dCV<8G_>hpol6I>@0uM511r*C|)C)vW&&KR(lkJw>%2H<#1rQ76I zhLuq+H;Ht6fj3L_UBc)rQ90aOscrFy%*6uN4pF*yHp+`E1>WSgpakPK9;dvb0Zo=;&PTK2`@^R@1KF2`{{M_>}G1 zDfM3`Oc{P=dxe@ITE2f?pw{=#;vv!c2m2JvQkE^R>;=T`Gx(3=qft)(-Dh3fD3b}H zy{cGnaM;^laVz!uTEgu~^~>!?wCZLDD;@8*TsE0C~4?*LI&i2R<%bau!RNWW|*QLB46uB%2-xfLUe68+x( zzUQt+9}Yh)Ke9|YuH-=jwtqvzQir)C&qsEKxg9ca+Tj_3AfHSf?@o*i${B=s;P+sE z_i-7Wu?_6uw!PzcJka491IOgCcwdwgf><1Fha>NG^D`@sw;l;}k{BWk_eY&h(Hlw7 zjaWj?g*f~Y4fW(bD;rD<44=T5Uk`f?4EIVqjDDhxX)B}j`s6)NBMrw zW9S|#`}j|EbYwL3EVprGkC_(@ZFY~2!*TiLBKwo6y7w&)k{)?H6U3MEV>PSEYFa4Y-izV~S%?}CzcJrahf7X~}QV|(fLpr~E@D^T}F*4G^w z%GQQ%YJFX@*7d(U>tST z&QR*Q4dZ))b2H$`klb8Hp1S2_QE3uUSK{0bbOunsdDgc1@Dahld0OEQsT1;hkGU)Q zI$7OIp5?U*gfK;_5i0nD%u~+u5G6;>r+Z~jF9G*!Yb%?(@TfxX7;#ZTZM!Uf4tip) zK0Z?x*&ThhR%KjQWE(|;9d7?Hx7o|075K#m3it~qy}j~FB?V3#fo$wdcA|D*D1fFY z#xZGib;RcF1v+IbW!**V=#GT;n ztpY0;WoQ*E*Yp&?RNh@9-XkbM|L6hp13_Ytc&%sp6-bp?;1F-nv-`cY`o=q zrQ6#ukk$|(E^zv7{3cIZ5rjLKx(5p`QypTaC$PKh@p;~1+z_GFe!(lxy2sRQnjk$$8Ehi`1EoTEC1 zuPjTH-^VJNAw%m{oBqc)4|~h58uPSc8h2MjpH<+zFWsOSY(b;-*rZ$QwX?VE)H z<8pOWET@apX~|xBlS;>)hdJ&Mq3%u|)Pg?HBV`)HS(HWZU^Lv~=diqn6h4aUCVK#ACdzNN8DQX83`Ypc6cVBq2Z}YZc9?=Ur$B(IU$h| z-Il!#4QX>!5B}z>&0>aGz+sGFz27pj!*6-U!Qr>W1sr|KFY4@xx=rjjckQTlbn8*t zH?F40^E2Levp7!Sy||$sU8#`07gx_`Z>#Kb>mD54_1Lz8P4w);NZTq;xpliDqty|r z%beM2yN)aFI3AM5%T9a$Q2P36lG(9YKRUUS{n6~V*IbQ9|BycA<{wwryv;WA%AY68 zbgWh;3SRZfH1p+Nghqz^SrTQnHb?%)JYHz;KH7~czEShTKegzpb25hfA>VmSTRqg< zn@%G;fGRVwgBd%wJKSd3%JR2zWkZtT9**;X0*Y7qjhsGYGrLJH86H1rYddVhMw02% zC@0thTdLafg0IPmGB=PpobX0m>FH7d>&XDuYY+-gE8Sg7o(JCYPJaU1ULq*d+uLQ) z;7pFA30iDxOqZCIR>{-MD1_K03kCqpUVmNdH?Id;%%&%FB_!I^8INH9RKBW|%- zcp;feztPy5(v$8w|9&CbHCVwCSSBA+<4{)4+SjX?($I&bE9c(mg?Jr~Dub^QVO8Syf`s8Ep zKxd-Q>@@O%X~7YG9U+nE9g(kn@}R_UC(k&0BNZuM1rI#%fP1v%$-{dZ_qk8(+26dc z@qI33<+dnPHXx&)c;~6~+NS4#)(oUhudUbdBwRAa>kHyGzkwd_*S&`HnqFW*&lB}& zpTng%vuoEd(|(Bifn`ElpY(i`5M}5L3=cogD{{Jom!Vf7@0RFUPqA}YKO$7C zFG<+OEf;M42PK4+FY3uaHdB#~wAwe4?%;^{hjD0S`YvVjo`dfG4K5V-r@tp6{mCAA z#A-uT?*R$XJ@yZApJxq!NQ=^RJGyS^tyS2Q1%a_-`f0S<%oo^bIsHDHqkBE5XBmrW z@;RuCYQ^G{9w5+Wg*eooD3HQN_him2i+H>JUL|W#;k~NMz9jwVY>(WB)4Jvf46Ld@(~vwi1`->{FO>GsZ%t#Pl1`z&@DpOw`v_Dj30 zSNr)(Zsqfr-R_q$j4@T|rDaEM`m33L*KW*aC8Qe|Oz3+R>3N!TY&~+3lJ6eS?etM&j!(;?fhk>qH%Cstk-%P! zE&tKL5Uxl3R4))h)ZJAxHNBMV&PB5x*fUa$~5inbmFmouO8Vfe$Dk(v6xlYY`Hnz z9IR<4yiusL)=ZkC_2hPxUe~>9t%FM62-HUH1kVMEMZUY5jCZCNT+M8q5cKrN<(y*E zG0v&&4lyVF7)v5@6*f$B8f?AXTM7u9ft>sHWG19c)A~SX${Uk%T&zRafVqEPxi+X( zAp3i9S8t}TapB0}LkD=;?F1~+(_K&2dSlJK74CxpuE53$>2C%!^M&~Y<^_9)dBHHv zTHMV;$Hv#e0WJEC;*z#5gzcMJ9{)4^%M@!YvROP%i|^_mAt>Trhu^AxGl#HH?%gphlaAkmElx& z46^d@j+uC%U#8)3-o4*qoX$MXln_|UABJj;Pfqa8N7J)ry z0`|RI&*Fl!UO7q6UTprgW)|n0f0$ePfsEO=|8R@e#dMnX_IiG7GA9g{i#yKw){pPr zoln*V?XHPu+3u)Y>Ehp7w@w~~eyqSrKR>AE$g#?*hZC+&l`$puPE*K2Yb3>WVwda0 z98O8u^Y|k^-_USC)|eeBx3W&aHzeioR;KUhGlzS*eCRZ!2U>DESwC&4QzMz=V5+j? zfy8#1XCK+u8d#TPRvc~+bo}!(>WU2pWr4;!+`+Xo|Be~mushg#11k|wbk;rlBsW&q zI{?M?0-H;nu%W3Ouan|Mae=KVKsT{LTb@X_|LN(jPGmRObd{qsz5bp|#&YUR_sNe)wtoLm+D3+)ALj1Yebo$kXO~P#C}#qCkxXY5 zA|VMYhY>f{Io8~8yz%IPmI4i@cYVeQUY<#x_wX;vl-Y3zXVdjqwJzyR-So8^T3_pw zBj@!!H_-wNCuN3P8JB5M<=`Ft^VfgjRlyt8^+FORVox252CTP)r+!t{B&b<^8A0PY@i^Kly4I@m}z4*0Xm65DhXR_Q4%q`xadx7hg1y1MjG8y-FozNes5$QD4<}YE*-^tE+zl`gp z#$+~)nP%?3!-o$Yu0<&9`!xEIV0p~QHbJEA;0N2gZA(k0tM<|O3?^`f%4_+wF|*=l za|Mw(vX70)Z>`r?1((;;YYcMs!CF~wTo~LV^gi9mFs47x&!BJj`rktFkt^vE9T*b|3Lh$1h7}zntz(hHkeMY zSCmD=&K`HKT)5wBSm7St)41obdxQ_-=&~MVc5_zCLxtO-$3*0JD+W`;aa5*()3Pvu zJoi>gdUaLTdo%Bc7+XlVWlISS1etL910pCpVYfdzAU&a7p(ubkH`DCaaL|D6>^XAe zP{aN`t@|4B`)F&^p~L$>g5P0X&8X!`Lsm$4@8O06qQAFc4@S|vASw1+jyUpw&hfp< z>+h%h-%sxk{5~YV4;~jc!t%_Mp1CxSg8y0g5T< zZCK-ZN_1#sFx}>m4;VY$P!954oVWVUDR1vNWXNdA!l?U+zAGbK91S?y6*yOleoSBD z;)`J5xj4Xfekl8aC{ajcGW_c@!7+p?E*3Y_5Ud52|S zU#kIj?L_#A^me&}%8EK_4}60^+_K*(P)n}sYG=`6uZB^-*~XlQdwMzLcC>_vs-2`Q zFH4{$QUBD5YIs%Nxjntkr!vi5Ik?9=S+!P7ZBsJ+0+{Ny9xaghlZILUbT(i2sLtvr z=OnN04s!hy`CeNq%ZM*Dy(2I5tf66#>amAOXe1fJHSuQOXx|NZf=mChSP$2By1O2H zu)tgQit(7Dd^1LTwCBiWf6+v`>xJCw>>sM|6x{BC&i+Af@=})A$+Tksx=YK`PU(I% zARg^hR?RUr6~xrEI%0O@xR=VRB0TS9>P`#aF_YYo>jRH^WkuwB_Z&pW?}Y0RWbL;! z#Qpj(g5PNhIjQbWcNzd~Q)H{ZY)?57csf=QP5o!;5fT zdbrJ&oyRui2uwwK9x7S3CTx^Scz9^Z35G{Tm+J?}v9tBO|115a|MD9A?w}*Dx=AH^#8y+@ioY=RW><0}?I#@^U9r3_?Lh9nswxlaPvVP{MCAi)^EHBW} z?~$Q&nbPB+*5^n7%QBBvaLc&TyVK*vZUY5Bs_QHGiL$;q^ZbS3gp9%tz@Z~8Jk-aA z`%!7d+1=N=d-pvG7xq5If1lnj{~mg@%rN`PWv*3VSL?6j*I*2(oz}y z)3E#ZF@e(kR(ebco03<4yky6lO|zC%yMP7zX4yZcTW77>dS;KAS)(5e-_U>Xa=oBA zEqZn>eH4X9r!ij0ijloB20!#=7hPbJB|E#v6h(L2I?U@o`}cY6K0MPU84F)!_8;5m z=acRe11F%OwaW@kx)En;^A9{)``YwBG)o_a@TRHz4?W!(mpg4`T$fI!sh+f$zdh$sx4IL0 zZb{-SDon${954 zjKZN2p5T$|%*dTAzT4xO_sN9*lzj4kBc0Q~>E5vE4+egB2Y$ny;eb2CLA!$iyMqC{ z-fw*lz`J`L2>-B#SIvjh=J7-&Com-oAq=|ib#?7hdbT>W5QU=6q|`iR`{U{xz%hnq~f z-t!)1HbRwOwlxzlGf7%S>Z*;4;{O;|%#CzN?0iNl)*tVYgFtS9r_(!piX(w_{gUt$ zq#rEvJuBBWm2TY~*uIV)PvPo%VqmQ(>AiaPOjTtySBeUo!^i%HSbJ(9ln+T)E2?KLHN-io=;B}TVf z)4|>XI;qD+Wo0q_?M5poLA_3DF)5#kJS#6d$f%CrCVKwK zNM+OQPV4Skt6TL@<*wZvM`}Fec{2B;#R4O7?*OH_74>2=G>l;>x9yKK9+j7XeE)hp zok4p8ZXKQ8w2r;em$2nHIYW3-@A;eViEQ^a(e3ke1D`Yss(E_-=^Pos5KP|HURUqA z>~P8e%{Gfn=lQfw56VkG!ORCd^H@*k^Fed3{P~ZK>D@C1Kw1wg*Op-sy|a@EZtMO= z)*e?5T(rddhlOiQJ85mi(SuJNJap`!W9oViDBx}?6T}Yk_&A@_IL^FF+u|NrDnm{o zPqHQACy#rH==m#8ZLcHu^C#2D&yOrQ+>kXOX~ESMIX#EuJZ?Lh5)R}+wvg$bEn~Q( zRS!f0mALct@h(~Cra;d1v9;fYe)k)y_D;*bgN^$SK8d-1!@d?-*|j}esj!Z7c;5&2HJE(;eoh~p+q9FTT~*`W zh0TI^9#%&B8(OjwS;o_U-o9L!Y@up7JlfipF0Mxp`@b6l^2UIi^S^$~&L~UIZEc^+ zGdsG88QtB`-a2OTN?Mtwq?ZmlSA&ob^Z4J%5i@zKr$2VQN6#at`!!F_z1dzq+i3>= z_kA*L`0{KU=9aB$ds36d(9vb;c@6EOUOnoGXWI?Rjz{CeF*7iEhMT@DsA=*nzZ&$c zfNTfHWBN$F9**ZDQ(0dM()Xs)9})IOUi34G=4WJ(cYoAj@cpsAK2F&+1~`jM?iS+*Yi&DNtVTTj9gRPe39E6uIg4La!GK|vtPt0G)* zO7Wknhtm39+n4$9p{8)8jrZFU&!?4iA9sh#%T97bMR!hQaWj&-gKn2RDaN?6jmW-1fjMvlO4RV&^E9#_SCdo@ zoNo{pvxJ@-y2hJnc!a02`PgHRe`<}gz=!GrCYt6%%!i-ng3?YthrM&CC%H4)bJEO@ z1}}Yh1yXm?<-BxdpOk^Vo`G1}O}@aa$LP{8YYnrgjM&_RYYsew$X6Hbd>K5{r!_KH z;j;dba=pX*-|^1*m35azcBkmKBY%8?nR(th7;sEnpR9F zrbRudiD3Y>g7|0?(}d~4xHI02(-gx2ngyK&&4bQ68V`n%;kypH0lE!hLC6Ocg0_N6 zK&7B^Py|#BY6LZbT0w1~D5wt<10_MDpfS({Xc9CHIs=*o&4K1Y=Rg-g3!p2YWzaRy zD(DvIHYg8;F&|V8ssPo48bK|fR!|hw2a17`pfS)mXbLn9ngPv%=0WE`i=d03tDtM3 z>!2IC8h;k}d{7~%7_=2s0g8YcK~10zP!tpcB|)R0G0+5P5_BGP0dxtpbeFn&l?b}Q z3WZF~0~LabKwCj2pi)pds0LIAY6Laqsr@!!6x0Vwf>NMK&=lwlXa+O~Itw}vx&T@N zT?Q?KRzTN4tDu{pTcBc8=B=P|Pz9(OR0FC9HG-N!Euaoi6qEvug3f?uKy#q8pmU(} zpasw(=n`lNbOp2wx&~SW-2mNW1A@jQ4^#*$0+oPVP&ud~r17l-Hi4Q!ZJ>5g6x0Vw zfkr{&pb5|vXc}|@v;bNGU8Osq8=%{4tnSwGS_Iq*Dgl*(%0UrOHK?9Cpbk(JGysZ$ zQlL@LIA{Vi1)2uUfM)O3@XiCzgD!v;K^H+wpv$0T&r#7S@|s2WrQY6kJ3ayzI4#MKw}n4_RE&;)1_Gz~ffx&T@z(0DHauYp!UH$XSp z@u1Vm0~LXaK_ws;Q~`>BYCv_MMo<%|1=I>^2X%l3Krzq+Xc9C7ngz{+&Vd#{i=a!O zCD0YnGUzJk8t5kI7X3!2w-w}qNjsKexaz!Yc{ zGz~ffngg8$T?AdC9_R+>7U(u8ADww2s1#HVssYu38bM8SNufkr_Sph?gf z&o&4SK> z&Vw$4u7FlRS3#?E8*~$N3sm%0@VKds}Sn})Xy^Ip_3QT~fM z7AkyE$9A{3s>5xMDi-m<2{>F#WPeM9!|r{C*LtN-DaeiuL1)=|84X z(d(Kq_XciI_|yvHuZPb(J}HB@Qua3-FHLQ41P2q+k(i9gP#T!KaM#GbnXYu zfWHX3{;x4q$Wh%T4uCOk&wrQlEnxG(Zv{=f6Z21tvkSg4ORpJxJ81RqF)uOq`e^U% z924dUAI{PF1Lq3uIXN=+rThx`TkFX3-odsqN9I$M6~05~50UrioQP$%?j71@@{h&g zY0xBOH{PMLV~&p3Z-K9Sr^?V>%G{|D{FKR_cXVEJ2K-IXXs(}cx501Snkg#*U$a&1 z{t4($LG|FHCc6guGr9?W+GOu_v>u%Sf5~L;1KkT++N$+w;i}H#=tmyXx9~?*=J{I; zz7!cz!u&_AyX*)CZ`+i!LgKq^be%!a)4!)&S2`GPSpvQlG_~r-w;lXt(Bv6E zzANBM%HjSueOUy23Uv8fzHAcw6;N_s-J@(3yt5r{yyEK>f^P+tzUs^Pwe(BdHGF7d zq>s2vy$4jr?t$;swSzBtKjH`hy96e0DfqVcs~)3BzdNV{iq@DWfFllp&dvTE=# z(7+4IUt(CmU*Dl&rtCL?c{>q5(DMIs9CmMqK?C5=?^Hd0>x%0H7r<|gK>yDJZPW4GN3ekLGe7j+i=El^{h%FuK>`BmC~mi$l0`7HR)f!e@dsnW2Z8Fkncu7G!U zLHBP_kHLSBNe6yzm+E9aXtv+lT*#Ke7wtwE_p1!7vlaaOgQ(Yk;g^^5;9F}l zW$oZ^*J>Id=yKLJ5B<3I<&p&slc*Ye610rMjUYNVL8IWO>Y)D{jsx$+%^C0uCQJ8Q zbvgz)+v}%k2l#VYvJ2qzAM^W0u6q@OuX{|}_TM)@n!ravP0#wW82DMxd2~j3=I?p% zr6}+#KjWm^jR^P@DDSi%zH#vLk86D8Y#wNVI`wEjUsN5gGv$My2i-yTQ34XCb{a|u4d9Q#kY=l2Z_@8ogJ!&g>XP@eEUFsJ= z#o!|*`$f<%ff~UlO~&=NUj~hXpEnu0Y6soAvj~3GWd8#6E1+B8>z`2BBIs8^t>BX; z`*)7Uc?|sA6MlaD9^@CmuYhKz9p{Ln>uuM-pFx7GKAq#2Q}EY76Tj={?{)B_NVMz! z)p5{uIzP%VgI_?oZ5r2TGYE_1Kd50rF?XH=wSd3%LDl=1qidMA!B0P>dY=b<0W<@C z)nqSOJZ^w5ZB`lic3=ejVnD|CDldU=Kj6z4gg)>$LD%8f7r}pt{(_%Ai1Pcgt}9Y^ z2K*(`=XFhyvdiFa9aQ(GOqPd1TKyrFeFgO6pjPlRCi^M~N$Z>gKiZ-)H1D!*IRSnZ zln0A1n|n9Fm!LsQenEM3El%l&bPUhAH=15q({2Ml^C5NbYi9Qx_^T%SInX}^-3C8! zSY=-aaS3(;{N=-$de^|W98uY@qifCW;HOQ-wc^)6v*1^bXukb~`MV0fq*e94W3p24 zEuaN7hMzQ98~C%J+ogW{cLDrrYvx$*CitSGS>r$OHCeJI@H!`P927z4zcJk4CqPrL z`F>1;Z+|*d)(5^GgVnz8`0YkB_;%1)7CEcn^V?Lm0{TNx zG5Bhed4AM@?*Ju-{Cd;}eiC$MBq#0f8So2jnPY(^@HevDy9K`V!Y4BIF^j5*=eFSAI;fJpXeB>jUdiCHtKBE5qClI<T?PF@<+6<{qK&IA@Ie|pq^mz^*>Bj4!(`Dxj?>wp9Zab&d;|w@Jm^; z74QxkhPl_3M|bTMf?oiQo>dw51TKP)ps|?#z8|-0@HHRRFjIyhxYG!J;-g%f$??+^ z{AdU2Lb0D#2V_X6ew2e+Z_YHl%=-} zz6AZ^wTeJF0AGl~>aCr=tQhuGFb(e4VD)^eH-&bJB;?#q0 zjdESocdrBd81?S%H(gM1ad+waTn zfvg;Sdw*t_`@kprGxKN+{CUvgVLwe5!52T5DRaRmL92nVjDep8b(H&l%!9v1`OzHb z-#fb3b_4vC=hff81Kk2$1z$X%G7e8T{3rq6F_1YA<*D;Cp!`4cWi#Lx2QtT}OW<#2 z$=C^P9n6%KgRckWxA^gB0)K8WtE>&`{2@5DxCXvt$d^&K6nq49@uHswHQ<{-jlUh3 zn}R<#l$rJm;ET|ST|VZQgOXt`NM*{3!RNiex)f;Zz_){DyM0+7_>~t}7JS)t@WpYo zWdWHBeh~xCxk3df1?zPrZ$#^zkZg#U{{_gmK3e{Y8Wku~ObWw;*~XY=?4{a=u^&bu}Y|Aee@ zKE9zj*Ks$?U#_=in+M}J=2DWGe{R6M@O^8|>z(ZQZ5%$1%d+DajQ`Soo7=xF>v);@ zTOTmz`sHTjvryLFHZI@n7qio+!^w`{Co}8^!#7j8)_yR3Ie*XgAH#>VIoAu;#4mSq z|LYy!+gl9KTunz%{^Z^Q!@KuBUF+KFrEkIuk890^uP4g&CR*amu;R3 zm~+i9+y7ws~ga}P1Q{@e)I=e~D# z{shyH=SDUQzx`#{pADFEO=2_q+$+lt-_?LQ&wym7Pkq3AZi$kO$A9g=wbp(xePxkx zll*TK^UVHhHDJy?o^12-fcxAN-mL!eOu%O4pJxlQ-M<a}Ogs zd|QL0ynPz-22!pf4L8`S^eVvN4EW7|IK}mHRGp%Irl&|n}2hkW3%#6 zRK3>!p!?ikSntm>KYIuBrJBvthx-yvR{jOkXZ4Y__9p`4NACAzo4bMh|G7WAS^jblcC-G8d#{_NANP*4$N$0bbH8A-_MLkXn~hIKKfZbW~C{Tuf+ zHtk=>*M{E>m~Z{;+Vl_BKl|ITf4P(SmCvnB-*wi1o_-1$Fley8=(JMFJ*y#DaU?63X%KWl!c_-#Bsadsq5 z4<>2*r^<5|S50rNcLnNB&XD}QWv z#$NOL^CClTafAc*=g#Fish`sGpY((79p613TL`*$V>DOp7<+%7dncSs_Xgs3IrZ;U z_qI5`dt4F?x)+_wm9zEUpXVNzUW4wnjRhG=H$F6Z1qJ*ils@3|!LYySi+N%%1mu=(__y<< zj!|A>a*pe_{6?Of(G6qX#HHsD@QlfsZs9lO$a%>S@Pf&CCNmt$k+ZTP;1zS9L+kLr z$&>l=mLKFfb>uPM;`}uPEZ*%70mn@~MmgqJyx$!H&gQ7Q=ggeSq260izbJo;o*AGX?{`zL85my5lRMp87V@0S#8+XSr}CCO zmGhqUmY>R#`_&BhRpWW5I)r&-E59AMZkke)`2ez5Km2%9Fd0#mMOqo1M`P*~k&Tl)?1 zi~0~&YzwP9Ex_y=Nni*#wMFe;F!S>?e|L`DLkIqw%UU2oA|d5+vQ4gp=0^S*I-dyZ2|Ik45_&2LftHq%dGSR<`>Exv zmhSJ;a1_2v!_f?6ztaQ^W6;n>IdI@z8jjSvG#s<<(sWof{vyrU?@`Wvk9-8}D$Rkn z-=+D@`=it^0fr|LKH!$`qI?i9qTM9^GV+P$Rmdmm1J6_bOQ0C(u5riKY0`hDe^RxOrnxC=vXg*I<5B=0E<-nEqXnK_Xm?QO~?Z?#J z4)W+{+sR{a*ar*&$4$wq*&;#bX8or3D=39Z`J;(>jfl{rlmk~NU&)iRfOMzmedVUWRm!s823@X5&bpI zfwScI!5(?wdDA;b`4bqQQx04*cW#;aZOVVkac-I(FJV)!{9X-T#l0H7wtKZ6M(@?~ zp1fD>w^RNk${*#xvu1wT>|ZhaH}2K)kawRW?No&L>!|nlS-kGk{NWi!+Pi$8+T(;Sa=*IUO!L2UoL2I{w)-`l9fr~SH9X_QpF{bf{s&Qx zX%3t>`B}=J%8@(HA>iWu8omX}(SBc~9LO`6Qf{`X|Bc%;J({+ue{I_|o*mmXo=G!L znfc^4O}8_~&l;ZHrs+SoP4ju)tC~o*5+6BsiQ>NEKIrL^s|Gdf1 zQGN*NNjdPc$(JZ^L4Bkgc-`cylz#~0KgxlH4`?`x9?){p@qp^_4maH$ctG79HF=8i z!^mICf#)93_@5_#1o=&K;05EC&HcjntNnanxE1XxFa&Hec?IQ1kuH=2J4_y-{Ask8 zlmjOyN4=Ue^I4i7LpW#-TqNI?BX`I{z$L>Q@3(xZ(C|ho%wJ&m!{~p2A>e??TPXhs z@`ZBXxXD{9G(3|P8lL$IEg$D9w0x|Z-ZknyljGc^99UAR@*-fk9rX+t0_KrNdsa^# zc!TW}+N(zLz(Sfoo8vT-2j*9*d5f73RBFEQY%#+zTdCn#rX1}`=?+Kwqedbo+l4#S zzvdn4AMd<}zl!kF9PN1#d5r58XbxO5dGQVn$MOyh2k*eMU+V+1pXwn0(Hyx89|E2? z^F=e~efaQk)N`5xSIqpHnO`N}fpSW7AkRWGKKT)iPb8x8>5FK1qCoaX12hLtn0%b_ zPK-||2l6gG>-}m(^PTtTxBL;tM^&0`yhAVT36S;uVwHw#sY=6jiF{X%+^Y`(SF6-L zp2cSPZdYmes&}dTt-I9yfnDnUtjU*lY4|PzIZo!?dybQ@n|zh>Zq!T4f%&^NT)dAj z?a*!w*8q^?g(&$b@{i`gh20vi+qWcm-8KKT>y7Z?Jr zn)yvLzfPWuVh_U{nD?-n7d@=z`Q-aik7y3$S$4*=^kI!>6ZL)u?Gy2P$hU_zz87il zIh14S0as0ajq>M_{*(jrYgC>G3=d#_0t^8MYBU_F8VyH`{2<1kGzap`Ji{?lqv5zf zJ&b=Y)o8xweZY}+{Wk3lp}hqk0u}+o!)OP|1Iww0_Mw#W80KS?0~<|VPx%X&pHU8+ z_<-j36*Ip~^EmQ@=D_P8&~V-OfQGBI){%B#qSod|wJKkr9OIlzs4YS|$h$HRCz$5BTGx;RK2MhskJ!19b5!H{@sa_Ho8bLbNY5L5Y{46kh zGDqHi2m!B{yoGY;Uo(3*%%1zGVw8yb#ybM^FZrnYcb0P0uQ_1&6xwUbftMcD^y51b zG|vNaJX#3kc(mN)rIe?TACv=|AJcrDdQ8)OlIHJ4dqZ>J*~c^-t7d-9+`VD$-ZJ@3 zbC(aP(B1sURi5{_hO_8#4JYq3$UOORjZfR->VL}glhl6z{S(cBi;ru#`R)YQy)IG? zTzOpM>(;Az36Sevr9iHGHPvgmjn=Dwef8?!w8<9?SL)Rr-j$$U$sX0?_wu+-)lMGR zVYmony=rB9fp%qya^MZh(Jn>yI?@is_NrbI82T&6nI@0+ za$wOuO)tLVvE@Ia`~t(DK=}lQfMev*UQN&({RH3g2!9geNSXt$?NfKJQa+X=Z+e7) zc~7XE4`+lwg>(dlfTbpPDgQL;1?9kIlQ%t~@o9TP;}fGC{mH@}&2PR1!u+119R0$@ zCp16#)(69RgFM>RRq~&~c!~PJ@+UR_7oSwUOHZoaMe^flpMW9Ybu+(d<~PWH7UhEG z!2BjPFK$xvLh_$Oy9*2fBW7M_=GEk1LOG#1u-VMp%)EvC1o}Ig1N+Q8Y32juUq=5) zbKtm{Pnr1y`Ol-hpgC~X%;(K~j{Fxeo~1c(!OSn2`6BsA)FYY$m(Bc|nXi!lBJ!2y zz?){y4Og1qBL5}iH~0{+Xuq15n0YbzFQeSj99UuIHD(?mKZWr!&4IiV#de^XJTOMR zR}o(#>i4YK<6A5o&n!_7xJo(4QN;fY`yW()_&!VcD@b2p2srRTbwBn&bw5S(yB%ko z{M~wIO4`S#)Z7Jb`Gq{W>m>8GW|hwY**?va2VO8d*R0{~29YFRweCH+n<2g>0a^MB>Uqw4i9(aj*Xs0hyK8<=!IWYgA+Rp=qzlMAOhJeN7 zzm9PZd0^>5weM2?4U|{PfprHpJdFo6JjsI^?$Lu9-WhZM4CQCgFHsI$F!=?_znLR% z&4hrd4!mjd8eT`c%J+$!cQJ}(exH6|2EnK%7M#=G(B!n{+%2- zND%_&x2S#|F#KJlGv&Zbhcq4C7PZ&dqV}52UaQ$_p?nVErW`n7a=xt-{vPIolmq8l z)V*`&-qjW@4}5Qj<>7|eyH5G*NMFi9^CSdp{QJ#PyVC+L$9#S9D@-Rw0j4#fa z{v6HEB7JBMT>6muf9*r+f5~Aj7o~@_Tr?h5d-armAN7}VVDzxMJ8tGN)2iw5 zeW38qpq-~2SbW6t5g0y)b_y5*RvgiEsy?FW)M$G3l>cmwyfG94c9@)R426FV?F;3= zQIn@A|EI`b%7J``h~;zUh?dV;XiV0>&#e2c9+g9Ob`= z{)=)T?~F2>7mjK;`Eci!UxdF;t9}VE{7c9`UNNemyutT14m7s zqWoVVzbFTuG5Iv*zk>2fIq+^fB{mH2+o9OPT}oj;Wjnk;1=* zb`KZ=P9M|!J7?zeH2-y!1DXRbQT|65XPI7Mn)0#1_umk1|$;KdJHxupCz5I)L*S53Y``M*MWp&WSI zirwE3zP#dd_=?TJfr%z zX}*Mc7x)m+HF*gz{97m&lmi=0UQhXNqnuC<>@#_k^54ODlXBps$tNhkjB-Ia@SMr# zDgS?vUz7u{nEW#3zl(IC9C*v*H!1(OC=czB154Ufz7-h0g8D-_u-@c#l>a-V3+2F3 z%2Dp;&HQY;mir4d2VNondzhz@2d=hje&1-<{LX(C{J%%}1BQUb*HNU)rJe2RhWB zScm#Q*P-dOL_My5nE6f0{}}FdYWiKH`3mx-lkr6V)2ZoK+@=1zUF!c<@_&eO0t^B9 zZWjHo?o$6-OuyaqTgm@Nly8~?2h2QW<}vbrg!vxLf#YUAW#$v)ucF-395`dYCS_tH*xX?|bp(s*C*(sJ=~qjGB3j=9usH zk^fWpPjlduna`N{H2G_2pJ)y|Z{~~U{sr=XhWbErAm1Edx~xPsUHEPo!(RtveQ4~l z`an76<+DW0YnF)|PgCzdAzsu27WS$<9~k~~lt*9)SYh&V%2!c;DF-&2yovJvjP#`( zIAHQV%KrlCOF3||SJQKX^8bSLrX0w(5g3p8UX914UX919>0hV*b<`i418=% z8BX?_JN@e4T)+CaM01q)8^klH_s?0ppHq9$=hR*w@do-|Un-8ANB-;kEW zC@}orQSX2u;0)y}$nPOdr`W6 z*6>UWYj|dc)!nOxd^>~g@NG4^Qxj8nqA}KIwC|Jy`(j!yQ!y=<(=iR_rI^NhC8q8z zQ|}h$Yt#dlzo7Q2Ur>8|i$m5WUQquQfUN)daYxoa_$C|uZ;Y$EeR1_?Jg)9v2J$?{ zYFx|DP0CSTuao~f)IXX73lpkWZWsl!{JB7$3+baASW5nJ^atdDbJY7CxJNnc-8B1o zNyS1S+vgi`HLo*yQ&PjzlGN}tlmDM+cW4ge8zYQ&Dyi|FO=`UOW*p1Im86F667Bsj zw0qP8=8b6n^B{cqHp&?=1e_dE|M)fu-90y=?nX|keg!c6|DyZ@L%=qZH&gzVZJycGDma-Bk82w0L*_vg%BYfA04rPN+uO6`rAy$Q2-mV92W zbCEpovbn=ISQyUy(;ChSVE8XlF3AIH4C{%gKh38#U)qcxH=f@Pk$#u<-vobX4!mq~ zep4ijfbtt6At1l4LHlzrs`(5se0Q#MfpXx*7d3o*1BT&SeNn?#^f4`Gk&kJ4DglP` zbDe5n2b(|WV|F)c5AONRawj;cSUqZ+T4Q7a## zEZ4bC8_j{^raxi&=V*@Nc!7MLzAZy@_v32b{&6+$`?#7fn)yXDze)3gT<11ws*hT0f!Tnfiprs%ubEdQh<>+99PP+_jqWPIZ% z9l3wdOgS)S@>0s7mo)vEPii_||D=YecucWkOw(~-OzriJse7?8b#Kz-6O_L>*O{Um zIB)W^l>bPsbB=Q0tuc+C^C^vA^QSbOT0W)eH1H`+hq+Iw-n{88eag~-^0%OzQ4ZuA zJhWf*Y0HOCtNjTe*H5M>2hM$3?Vq8%2;rd|c=OX*-fmFN{Wi*h#h=l5w|_>>+koM> zqW%Lzz_HJ${={cgf0BCWSFacrjVtmEAem2%Yxu^-9T_K2kq6Ejo*UP2UpD?G`CmtQ z{j7%jD(&5q>ud!d0;WEzdgGtf@Qnh)Z$o=PIdIP8vy>MjzLWzmepcgk+wAiK5&d;P zr+f=}^glD7Q@zE{ss9VW@Y{2pCF%kBc9Hb&pVN31zT`;1>%OG!RJ^3_RvX`J*kTxc zN#i&AlDgmVlE!c1C5<27KBD`VUsCs%U()bgH~9^dyAvAEk_pX^(h1Fv`U%w^HS-kB zG0zyIIdI10XDG)!W0rE@#R&~}@yi;nB4GF(Xm@}iU>)Tcztp^}{x!X<{i_u5>i@L4KSep_4QD6^^35j3@BGUeziTgRcq# zyp-~-=%*+LmXm*1uG2~$n4%uqTfX^3_m@7e?yr7c-7ooqy0aA+{?S|~0t^8gzo7Q` z7L@ekUr>8Xl>ai^qka|UJ(L5ln>#ltpM?9wcca~-IWT|H(R0R=>Ta9yG2$;FJtj5Z z=7>Lw@@Kd*sqQWV!zF09c?2Bq|fbt*9bw()% zj*&;dFiCTaKgP+wH`h5sbKr$9YP#foN%ac9ql6b+z>+D;XUgwGIiVa_XYv}#OOfxC13OIK zPI(#nb;^O`CLg2xezg0P1LsUWOZhgmJCp+#rZoJEQyTu2DNWaFQ<|<`YW0rtzS|1TfV~jlR~!0`J~FMuInqsi+juRy({92otohNFY>N|Zm!fs>{` zLHUcQ@00@dWt;o{MR%+CMmB%y`mgg@pbjT{_7h4=+`aXfZ<&zXTT6}?(6FB{MXgri-yZz zSO2e2e>d`ra$xy4)Lr)*jDPEh)35oA`WrR<4w^rVa8nK(Fmt|j$NZlCj!0K;lKDB>K z-D{RwU*>R(a+ z`d+d0dPV&kct!n-lK*4)LmoK#iuyPHiu%Vl{bXG8iu$*8#*uMsF);iH#sR<(u+HQ) zl-I#u%7Mul4c8Rqf8sbZlmn+{)SuZI^=D~D!+DAFM^WD?2VS4iaIem2xNps9xC>uZ z{d{2fF^mI&Az1k5OKadP+I)!mAqIE0q7K<6Na2 zxcsVy_u8u(-lEskejzZt2mJ{!1gv>Y!&OcBUbKsp1KVD+{C-X25q(YLkuv?{YZ{O7 z*EAk{3z6}de$C47YnsnD42yq4vBt2Si1vHNaK*4>R94F-`04K8$Vh2yXMrJLjmgU?--q;}9LTpF8Q+2L zXnZGVemCkJdEm6+Wki%#sK4ElC-7epkc8H}%=>-ZspiQ+FbU6~OR*_zMgH>&Sl){*ni_&S`jB zD1Qp|opRtf`DTQJJaCHq0fdJIOa4QD|71qRq}s>^rt@Xn(=kt(|k*QPyLGl z!v`@Q0EU1UDCfH0_cYuqG(UuTMswip@2UG0uWPufU)ONey{_)nP~L)ZHs!#!*EOCU zuWLN}URQUcuWLM#uWLLeOg{d)rqlH6nofLklkq$Iy2fvndgvdnQSU>iH%f19tpC)1jU6k0Ab( z1C!)YpGV09|3A*oKfc|2UjKK~$eJy)+JYh|Cn$=Vpr|8`IEtVnC?_c5D6;A3=qNH` z>n4uQiX!N7%IP7jhoHzgV(aM0oQ|NZh$E&5ia0ug?{(#MRo?bk|M`CM$Mf^NUhn(& zkKFg2ca!yx*nE{fV)MoCPUU>HKVtJW{!y=cos#&dZQrDr5~o>zFZQ>O+WuTnUjC>} ze-jM;6OISw;K4_2ew)nGSdYv>ekUuZ>o3`Khe|e|!zG)~@sbS}FWLC#)qX+km(_k% z?Mtd}s=m+RaebBim@Uuj$85f<`R7`490v zs`?b`GuW?K2eYa#sh(&3`Pi>n2RD^(Fnj zE6NMZU*z+O%)#;}Y=78f{?Axm=3wm;wqEL=u=UbrJKXONe$v{9z~GDVJ_!cEiBDR6 zTJ;p`vp8N@2lJ}0f70e-jrEsc`B(?*%D0)n6#FxCaImcLg2AuiyhF$RW}5yooPWRo zn4@QL-ll`A^mFn4NC(&H-^2b)2Ww?p?+0buz5|~!kABMLV;Bschw~vA0F%lS%wLZ8 z5$52c@_FWSm_Bo`qVEfU*1GQ^1eS;chFy_BU=hc`meohV;Oj7c=3rXwrkTGU(_s!SsC}OP z1}uksYs@z2_LQlGW)FTsAyI=HUkHa}AX$`ga3o; zWIC9m^ZkYnR>1CaqW{wPz~H4g-oOBuqhE&Oj1DfVU4i*qu)dgs6*>-|Z93Rgy9RTd zzYm#%k^i>!lKO8=4-6J?T!8^FuY8{Q(!J6_N=I`zE_Lze$`SZ5H zBDN1003+MBUWT`Ay~J4m1FqNT;P|#pC$VkQNpIV9rkTGF=P~Bs?6!?ROJ3#oR^+Sl zBKdyIKih-bn(mIK+upYIeaLnn@O6JYJpc}Xd@eA2jctdKYiv72ud(@xU1Re#eT@xY zyvEk!3hQe)kFgH&JM+8GrN3m;oA{D#$K@~CcH9JmKgafE9V~yz#=rX|E%%qrGha5Z zeA%Y6#r$7!USurVpi#~4+WIw8k>f5SURj;Xjuw%>BWd1?C z|1bv!uC?3`2LH|Hg~0$ga;=ST>{=V&=(RS!@oQ~-(;6z}5IXJI;j`@dhzGV&; zn19gkl~mtg{lmDfVIADo^maA9ooj9Xs$XmS7k`U@>;3RrTkoS^vGtz(immr`@}sz( z#jY7Vz0cc(^Lyd8l^=-NuUNgMy7yJDdp|M+2ET#h3JideuiADR|Eg`LDS83R%l1FU zc)n`K!-j_2)NmyYSJ7~FI*zk_I=H8LQ+0pMmOBLUd^kY=cWehR0FKsd`%kIewA!WU z8+e~#J8)6;e9hKhu4e16P_y;N-)iVScc|I=+o{=nG-{fU>pc6s`#NhkbDgzYy3W?` z)^*yCue0|2?S}4s;@7O*(ATUU{hHMis!yt(XZ=5L9YzP2>38n)R_Wk2{ZF{Arh_{g z->$|tg!g)Wo<9uo^Zb$jvEwGn{3AXu#vGhyekG0%@y(HT`2Ip@$zjvm* zYy06Y$nQ7UV-D``+Il?Lwe{Gbe-!&4>tOtPo9+Y{EaChL2EfhhZT>6Q+x(ZWxB0JL zZ}Y!L{}|4rbg+57P3Q1>o6Z6K<2Wu^2P0p%`pDO;QQr|@;#K8Iho;~|QKF$0yIL?@Z zi_H1C8}mI}e=-Nx)qYL+rt)p&RpwhhZ-+V9RNi3zS=`4l2mRl&@q1wKM$a1n1K{|# ztbL66=P=*Q!TE35dS4Z{zh&F2@-5pwJKwVHbEx{@w~g^{+xRBH;ODVFfdOzNtbb>?78`2q7U;5w5zIJjry4e!}_ zqkA^qA$k?(KQI9Dw_LjClRevCGkdmwX7_A)=QteuOYYfn7xrwq*O}vZU1NTSK5v6L zxUY5xYB&5H^U?2^^S5ETpGSPhrdMVCRBS&wxCipQQfEGZ@i7P6%<;ZG@m(8V;=4A! zY5AMS7#p zE3pn%8hWnUu>GygcDO$}><)+P%^xBMhks~!1Ps=2y~!M$V2bG4%Y%@ zwgaR8YxN|^{Vesrwx2D^m*iV)hxhq1b6#gK2b*fwQakTQ=Aj>%=YC|%k^hk`$Ig#z zJlkxC`-wVp@aRW&ypJ|*|BiyZUl;>%er)5J`mv2?8RU7mz#P{aE6l-7u5YfH`;h+ZnWi?z0sB@AJm#;4Fv#0FF0tPwks(zyDL4kHeqZe6*D} zeroe^r1{`)f^q&we`fPP^E2D-X)uU+&M*h_%5%&y>=JWu<7c)U>&(B7>t5zynK|yq zY9y}z_DP%{IzO}N5B^;10StZv=QBDu4)Q*#^mALD^3S#3{M?4y)o=%NoOfE}<$c}} zbCADb*4_VGwmg#{uVWKnu#Wcu=HQ(2O%m6)gTFAwME=$p$Fuee8&CBYHvQ%=Z2I0W zz3z1rfAfs((!aEJ`Cr=dmVasO>%X-2{Oz;ue*7zI7x|UdM}KAYr0P?u&;QECv(9!n zwoA;x4Gp)Y;p%LM>m2`~XZ_<3tsXtJdg9RLbAtI1t^=5Z%ZIjp*A8v{u4uR|4Yzw} z>$gsR6W6EALH-6C=kw^$=5zShHr&LoZMbQ$`}YCA)_MQe*6!%nwmjkASo`7MSo?W- zUcUYtTmSs6w(kA?Z*2JRZ_y6xG79qheTIH(!^M7U!_EEHw&%)kZTK?zIb1*e*7naD z+kXr932YA@{?^t@qHW_FZ`=5iZ5!Wg+lJ4#ZTKAP-^TIII=I%h<;?zr%~wt1sc1aA z8qY!7*5hH@_Wu_BV(hQ1gZ#}oE@$|6wwxosv*E{nXTwjao>IM_`iANUbeyw}=wM6r zj_O1IXY(Hh`F*ZYkl*JzP7h-Lpo3|(n`X}Mb7c79*Ey?numtivGJ0g|C3a-%WsJUu_eU@QrjBg6W{zyRrjKm7GDo&t3mgvT zz1)#aZ}rHg*HpVhwQFcRM;gz>P1?>kS$+H_tEXlKKkC@{lYg@LnFRU0VpAZ$ zS8V=I);{+qYhRRa$g3Kz@+Vu4?LXOaG}W%HcA-Dp{PQ;yyZ42Ew)xEdncE51fpl>0 z&o*4)&ox1xLY=21p#n#s>iR+J*zu0;#JjTYq^A{UWG}G){WU^98{d#m^8xaGWm2B<+5D#EIo5xGzJ=*C z2RoY15%UI)mwx161myREMZw??aUH=N9Al2-Y`Wj(Gu>~~&nVCL+wv|eFVe9+*W@jZ zkN0JMV~G4;pEm>sK>k)H=X=C&^Ic&5M?P z0k#Kou*@9ip}Ok3tpC*KHCP9al((7x4BO!pZUVBW%h$sEim zpJDzBT+cEG7f-S2^S4I3&m&K<^;>1m-viKa0|U0cLIbv64h`6TIR^54lU9A1^8L*mxsB8}De)h8qjocqf83-c-=Wn^V0UwDDGhHeUX=DaTt6+IT~! z_I1w_qo>+-83B3UFb?v*Aw&N?f2RZv&WQ`B+W2#)+Wu0IZ=Y)W%i*aupDhmmE1%b4 z9SohO^#TSDv7dqgFv|P~elM>21na-Xc3>S$E1zcm8*B&WV2*wruJh^O8vVCEZ-WkQ z(c4&lI=G|pY%~8I?uVI!E&BiAx{(h0LtJjmZ-~o_{f2&o`J{s}`c1gsqJv5LA8n=UY-uF(Eo((O$ST#KV!e9gO!lY=N9w7V7{4ydvvegYtX@F$dtId!4)as{ zy*=jOf$}Ev)B3$ObI^Z=(;vWPjWm>)^if5#~?x zc?ZnFj`AbsDW5lRo4#&;+{kTg`ir-*@ovbs#42;VzwMpb*L^=b0Qo-HJk#d4b*9bl zKK<7H-Vq%voMr8o&a!qZXIZ=ASvLGK^E0qtF$cHRzN+>$wXduF4)Z}AU(CS+wLen5 zt>HQvu0_8M_P;P3jD)TIP}tfi343gE4xz-0`{(W8;DDF}gLmlnQgm=yT)CZ1r+7P?&H??7IDYA1Ta4b`rWXN&cf#=s z2Ec^!IP(aOPv+nb{mz(QI=H8Hb>?@$c4H2VAQ}labebT`>4VPs;g7Xn`a9MeQ`MvwSRpww-d4>6Xa2{d~Hk9u(zc1Do zbCAD1&i&BCJx}*O0Oa?KM!@d(D>4TYbbe1Co!{GdM;qTf^HH1^nS-kuenrC z#YuqtKAfbOW&H!#-$}%*l;oO62F(Zi?y2pgAc)e$adhC@-lPm`xWM3 zL-{`QhhqO?4tA6uF(1cqa#!SF^sbfO;d;4}-x8%pVv4W5c#Tj}6=Y zJU(pub4u-}m_HKN56r>ru#K-MZfW?khOcP&edT+~8_JJ{?Ktu7*4I5whVG{M0)u~# z`C<-EC?9A3D4gG!gK6c{%;T6Z=HPySwEb=Kp~AMR)*=C?5iYkHP#i2S=5UFi&9nGY8|!CzwAL`vY?@ zrF@F{KjQqz9L(I^j@wx}SY$g~hpe(4_VG35V1+r3H}CJP-eLXueV!lA-_saY9s&9H zxKZX{T=@j^$6;m=cR4c3w);!RhCkFUSk`u<0HCv*oMGqc1n#l8;@e^QSy~ zPfRa~{RIqw!(jJ&r!KK}bN94%^Y^s*TD+&tPfm<|)Y`47-6n^}c{o z<~?n{NNifWL*?;%q1}_P9>4&YJmwdzUFu%e?&t>dtUPxwZGR5` z!SaYrca!-!IIlAY>&kbTKNZ(m%)z$uL*`Gzbq{ked~fYPU@(RK77T!6_qOeq6-%r? zz27Ud4px}+{KEVhI1ZSD{`=T|-DdtwykEcr;N*R*{TRseWs*40n;%a?GEF z>rv)lS@|aOXXE{lIoQ6BZRgH?Z2NlmH69$;c8%QEw(ID9wLD<(pZdLd=HTLeZTT0N zr?EdW2aC#AnLh{bN6f)0{i}FiW_{1^)#%T~dS@MMseYvTA^mxnKi0v)QL7Juysrq; zXK=iL0dQRPxat%1=VSe`4$i7RuX>jL0?aq-;Hv8Dsu$@m#QBPKu&R1Z^=*0v^Upfi z9JTY$0UeCo&&~%kB<@@Nd|r$7nYo{>*F`Y+B5XH0xFnXkYZ%T*N*#Lxqc z@dw)SW*=zFJNrN_*8^?%?FZWO9zM|Kw=-b%w(0|C!(W2q7z}{pXIs12*|uDXvu(Lj zXWMd3pKZ&PXZ`WRCOQI&-k9yuuvkyKUxRL-{^)952nY?YId&$d)S# zc0Wf2`J6NRAZtI%9LLcdb8zWFwm&XE$o9v=gY0-%eUKdwn;K6|<2ihgEnkcIOR>F} zgM%?!zHrQzFBh}%7QpWBjnH3)`!3eOy_n6X_uxMJo`(n9cF2fp z9Pg}yIn@gqK2Lu+mWOq4L-n$TFVW{PKdgf_)%R52rJs-EfOYUt^^WRo`YUig9Y-Au zk6V3s-0DO0SK@k*b#Pqu#JJ7h1brUoE!M%b>a(iP&@aICHtS%1+_vA+xNX0caa+H| zaa+I3^jBfOq=Or3UsC%mwXdpunf?f$w?hYOYQL-Y0}r$96@Hj)uh7G6_~D1y@QH`n zem24U)mRSZ-~w~p7p$nh%=!YZ4_F5`nX?}f^9ynQVGh>Reuw#Mu>Ua!TgscvUyJ>j zIXLie%l%+*5%0@j033O^jX%nKtIvxu2QzA)W_|&#BbkFM54ZWPJ>1rR{o&gF^w;6I zWjk>A5!Np82wP8+kFfQWeuS-;*+#(?yj`|?JM9|_b~@ks%KQ6Vf{@wA2A0PR9{j(&w3u$ALt}TSbsCNGjniT^&N82=helA z+V8Xd#aKS(p!fIIe(>+D9s+}xVELGXQPpFrkFmalWiu` zuzneqk2$!k`kLxR*588VV-A*8-&VcKdI9GR=3rCxw(5thzZJ{%DCFS4qpUvkD62>1 zqvXHfK3MrU7XWJ`STAC^n1gB6v#QUs{yr=hb1D4z8~@;;J;!!F$bfn$5fBY$Jp+JSROiF~gAQiIRSmb!`@*mE zc^k~ZDv9HEN8DAr8ppGa^AvONP}B1sWAzT}AHsTv2f*-SwBA)827@2Q{4oc|Ri9Kn z!TP^rewl-5)w8P4vc7@$OXgrf^`h#ltp5kzADM%js#jI7u>KJoAI!nJ>J8Of@-UAN z9G`7E=q2DE#qkUVz(H{`VZ-IP+*ohZ30r@230rTS&tScR3-W^6=Q+L-_6z1sHQeS!5);P_<@7F92)zQOt@ar`m|tE%s+USqwC%0w-eUdpxbI~S`X6WY@Z+pL2nH*7A7Bo~R8OcLXZ^qM zKENEDR()3W4D0`m_W|bMqUr_JmstM-mWw&KruwGpCDyChznFu&sy9^MXZ?%VznFt< z)%}y&zrf&CI1a!7I5cVX5!IutUybEr4o;|^RDF{5ZR}sn!K~_wsxPp94c;%9gUhO~ zsa|CLOW5C-gJspXRj;!CWh@tSa8LCE)tjvE;JAJ~a&X}BRv&u2)x%)$TI_Gk!BN#G zR3B&kE7;$dgHx){sGes1t5`1P;JoU2)pM-ZaNIBl*Htg8zRCJ^IBuAOJF4%gUT6Jl zIBuAOE!8`!AF=*FSgt1^2M3>E_2DO2Jpu-IaojKm9tjOz2M&$0e> zyzemwmsDR>eTDUJV7ZusCDkjcZ?Rs-`IkAkuX;=M1J=KZ_d({M_e84?KGEtSF!(K; z-KWB%Sl`3-33G5k^(EEwtbYgRH|Ahb^^)ovtbZ5hH|Ahf z^a(o>0L#T3%&EStdV%!@&UehgP1UQaS6Kfc&Uehgy6R2UYrHSv{-(Ua_Wz6X!;|3P zAjrStj)MF~-|1ow)}CzhxyHPS{fjy1e~RVn%zupa4-bGN%1g{|#Cm5A#+7d{{|Sx{ z=HTp8Y`HdhKZE!6EOT)FDYo31r&zwAeB(|w--V~xe7Bxr%YX0`TmHkR*zyld+46^` zZ24ng_xl*9Z1~A38$LOu^+z^vzGU9QA@zH}ni!?&LFUe3M}J?@ht( z-DHq;=wcY9O4-^zQJeOa*jOHrW<>vO?Q&{dvKmszNUQlnd)!(OdCElZPQ7U zU&3`E82q#6&42;0Fm3Crr1}=~U*NnU-(mY-;=ITl>?l8C{y3ZupVim>{3r4(%ZEUI zzBs}h++aJ5Fa9hWZ$j;I&$9VmewNL5L-{`QzhM7i4tD5Y^?Uwj_jRAUd0_BYIPSp! zIPz?(kEuRNKg9W#buj;IP4C&Z981r(<)|p%7xz?es6O{keck7)8{(emPb*K`bT`vB z-4gv}cs~L8e73H9m-(;pzRw(ND?eoZ8@xX<2gA>?d=L!&7S}Og0E{UgW8TJcF$Yu1 zrm#15}Trb#+E-cWAiaEW6K|&vE?6A zKFa+6upG?6Ddou-TmICHE&rVI?2Ik{{ERLCvhu==E&s}lE&rzS(u^&CdB&E1S9y*3 z@39@2gNMpn%#W}gn1h4Qw>$&}Z^Hb80dP$DDDyvH{+WYQ%9G6hi1}v@&MD6_?_mC! zgUiYb%>RV>XAW*EFERf!=ASvZtGveiFPMMk;NkOaeIKdbrh7OZUVu6nd4V1G!*nnK z^0;4ofen{`fen{?fgK-(7ufN!O~>)K_X0Z(kJt|9t2XmKZ08pu2Pa-=`Opj5p1(`S z_WZp$o&R2F)7^QYO?N!gXWu)OvHc}4ZiKQI8sl#emL9o9Q@Fr|Eo`R#GOVh+wLpJP6R>ni5pCjAcBPv~HUen+fNI=Dl> z6V@jktkWY{pLDP}tNn)go$)@+9Q41$at{pN1?v|KfWt4b<0482$63dIo}_~r4#)3* zB0s|4%j@fYp0U6>xb_lTUppF4P2=%i+SmPloB@#Ej}v{Vjd$#&Hr^!t&V62r4$i(* z`y=za;`nC{7GG-HE&MX84}!sAtamT~re9{q>4NI>tltg$E$d+QWj5X2m)Ud=)ZU-f z`T&D>$NB&R;AqzBN!2G=|2zJE9_rw{>MN=*vmV9qz&cn}USWO@tPkd3L-{`Qdt$$0 z4tnQW-eG<(9MA9oIIKJZ21hVo%)yCsZ9T`&we`HfcDRn4V>_?U%P|KxmG7Nv%YSgL zE&uR&<|F5s$Ir9rOfbJU&JWDN`SWZ#3+LH%Ds0E=F1Gs>&RfjELwXSBM>^Qi_`@&P z{sVUVagv|r@AcXKa`1B7|C@B&;~la+7@D(u01V=uXAlg4b91);jWPfGK5w2m7^6R` z&s(B{n{4+#*ly?Bd`zEj^D%$E&Ho(pL);fK2ba&c`CmQX=6~~iTOTFn@jkD@96V6I z%ly%pU*=%s6}Eqlzrxnn#4BulWnW>_&%eT^UwwrgM|l}|IjKaPLq_vi2bSw7GF0eIhJ4z4I)W2Sg5TDlajAAoeHb zU`_cB^Ruyjn1ct(o6H}Cp7n>~eU1*UUSR9Fc!AdQ1-5?oF0l1`q~Y7l$1z{8LJo#sW%(c&d>H17`NQ~o zhL(>qe>mog`NR1;hL%qdOVDKNXo|%KA%14+#2J4wQIH^3r zJc0Gi9Ly-6Vg6VgkIccG@^MY;vMYd!AHMaBhd3omGy7D#VeSO{r zbFj*M3+q$$L)Mcx4p|4I7xs0}i%D@#T)R-)5ez;F*C${Atka*2_YXSQy3qE=_Jy`T zj=aXE69t1$!Sx6j0F$q=;Zm=$;WDpLKj7Ecaur#h!tqH58ywG-IRC!3ulsjMb7Jwe zHof)N+Vm>&9r@8~bv!UX2gk!A@^komiSOe$V|%dK23iHmY;QS@pZNya<8-Xu)%g^tZ%ma zO`lg{4%U?KFn=cYE9T$<^9HU%Uf(K2Aj`i)i=bd*iijQK9aNLnabIAp3d2J-eUeOY?q5{{DT+S_`N6F{Dm*F`3qfS z!wp?z!;N2L`@w3;+D)ikjP0I{^8_6ndV|#`RrgEs! zUSbZ`l3Qs%Y(JO)dHpu~CR^WyH`)4JeUq)vn!GOe z^6;Pac>^H7$2yd^=}a)sVt$!}$-FJ!B=hHE`!WZ!%4eCs0PB@GxSY57TFKjdl~}(D z%Sqz+s&F_QUz_xoV7b{2+++T3ocGA@VENt*eiz&K%{IQsn{9lP%>NbVRWSHc9FNSw zJo6Lu07s@GNDQ@zc44fA!09aoc= zSUq`()mJXD<*t)2!+yj3W&Hh0w7(Y1w`9jpYsse5Ub5+gF74|+rym4Qdq0j#@`G63 zOKtrvDle$rGX2X~pOTi?mc zY(8h`|ApzZ-Fdj4U=9|TzZ26DcP_K}-@Q!hNqL+371&?i0>2L91%ofgc@_+S*|*s8 zFTKUK=Q{ZX%(wF9TWouJ1@lP3w(A6m^XoVmoWpe}7yxGqww#OPHr{^Jab2K1 zsyxHI!QW>zu93KopIp{{vTW^Um#v;7-;DLD`ljl;s*hZ5`RL`EpUZ8!Rpr~tJIpV~ zb_av6#&&)?a&Y49x(|H2wVQjpwabFR1sp%j!40)5sa=(IY=#{=c&K_?_0Sbo4_{&R zr&;XaY-zQ%i@Z-Di+1H;=ES_XB=R5W7YD?UI4Fk2 zAu%Eji&1ez92LjJm^dy@h;cC?PKrr!N=%83hs#R)MkCd5fGDNczgaav4^Gh#-Z6|>_1?{QHOm&Fxv zRV<2Y;<~sYmc&i5EN+Pvu_|thJ7P`T73<=jxGy%urg$K>#6z(y9*G^%^BMi(fEW@7 z#jrReM#Nz;DvpSw;+Pl{$HfUTE+)iDF)2=oDREj%i!)+IoE5X;oH#Eoh>K!Q%!^B6 zL0lGB#8t5Z2fE$)alaaXL1d*Z&>5S!wG*b)!Lws<6VM6ciI z7YD?UI4Fk2Au%Eji&1ez92LjJm^dy@h;cC?PKrr!N=%8EeB zOFR_Y;*r=9y;~Xm;(!#ThXp&Wc%aPMjAP#6>YD=EWtkATEn5;;L8_*Ti*kLoA7#Vp-f0D`HjL z7I(y&xGUDhJ#k-bh)wZ8Y>9_rTRajwB5(Lfzc?U<#6dAE4v7(QSd5Az;;1+##>8=P zLX3+EaZ*f*Q({V-7SrO4m=R~itT-pmiwokSxFjx%tKyotA#RCPaaY_E55z<9Nc4in z0dY_q5{JbRaZDT+P`7kww(ANo$XAM~AY|K~g5e$RKp{hjZG`#I#dc>nep|1ICI z`A)b$L;G92AM>4X|K&U3e#>{l{gv;8`zhZE_fNhP?w5Qg+#mT)xF7PJaR1{w;eN+= z!u^f!g!>tu|K)#k|HAXX{BQ18d?(zW_)fSV@ttu0;XC1e!*{~{h3|y>3Ev6#555!b z7knq&ANWqVAMl-U{g3r?i`V=bPFNvFKUy&bQ z-*2n^@pXP(+*96^A7A&klpkOBcf{`XKl0GcuK&ZzkFWou;)wE?{P;d#LizE1KvL}9 z4`BY&^5gq~jPm3Afq8L3d0u{eUrr2P24VZ^i|O z%J=0Bv8nt}-WHFP`$OgfVkl(!kUSy|hiraEa@<}nNd|I9sXOw5Z;EB*Rr$8Kqr5KP6Zc8%4+rv=c&PRrxp#)qe}=Uml!wKk zGpv17J|d1PAD2&vapg(*l$cUJBhQGl%ID<^;-c~;c|lxOUX-ti>&iFfWpPXSwtPpd zDc_Utiw)&1`JvcW&Ie@O^(77rS{{}Ui4o-^@=uV<%jaNc%(Mhx_m<{Dc_P;#H#X|d{?Y1 zZ^)bCf%3NeNbD#dIMX~N4xVXwL_RD=NuK}ZF>ze&6Y@zhseD?V7H5=a<#Xb^@|-*` zE-7D;uZl(G8}gF4sk|buirdO}<#lmSc~gEMwv->qJEC`%<)O382gNXn^)oDwiX+Nn z@^NuO`J_B4PHFsUxu@sDesO>d-mE{TPwj5R^vP?nACvF*do!x%$co=vlUK?A@OusN z%YJ+A{Bgha|7-f~x$%{L>yPKtbKlSC`7VbS8)CQLnNQDGxAYvAVx95#M^&|52o)_lCHL)so`^)^m|JUbo!(v?QK0o`A-};64de6VQ&$+Jg zTYrm7{q~&dbAIdpu;TygbEX+FC$5QAvHLvdV}5&XGNz~@3~3$`N$Xj z_BpXn&o{XIx*tD&J`opZ#GJS$9zO?Yh@S3yhsC&fe7~I&*TkyW5Ix<`4U2JcM$C!F z_m5SvA$q!h85ZO2{TPQA*TkyWaPNCKycic}#GHG7!QsV*=;=ClSd5D^VoqEWkFTQ} zqNnS@pH*k0{F3yO@@7rr)Rcwf!-VcVwxHu!`#5M8weW)RNI$sWpaq;+kpA*-_s@M>Z z&#S{?T$~Ye;+j|$8zMhY><%x+#ThXtu8CE#A$qsf@M2t?5p&|2SQQ(hcRLL)#>E*i zC$5QAu_1c5*YILooDp;4nph>jj_ptKcb zrGDvnaSHrQu-pF_FKn*vGqdjBf8cd@uy%=O*ByA>8w@{6pEKiiHoSGMKF7rC5%7UK z=yNf=9>?)vAI_=$Q$72w_IWw~E`+~Lz94^*=XHNe{doN6dG?#T+wu$HV|P|RW4zw% z*=MnF%^&~Xqta0SY`i`U58X?jhvW4LF8`nP`88gjhmYRVv+E?hz67q0_u5|%kABg! z>n6N@03Uj;K5xV8*POo_^!XHCf8z2ls{a9Ax59AC-|4OITZ7ftslPH_{JcMTk!ROy zc-to>DBYW$QpZ90t>Mw!UHSolq{vHIc zuXB9osy_o>KjiZMO8o}#`Z+i_r@s%ui=X>XR`mHJUi`a<`T5@R^kccR=j(HAy!iJH zdw+fgq;@>fh{7l!$c%94n$*7+LUa#W(d`X`><8=vq zH-y&*;pG?T?=$fFEVzHAoM1Z@#8CKR<&XJy886@cJFNewO+z;MIru z@Q3pMOj5e8T?!VJv%Gei6KKJN3W8>r!|p zs(vwey&Jy#etqtb*S~|aAMEYVpMq~(u6`kSUB&60*Ju3)@cIVG?-W{7y#eQUMrDrI zZ@+!FQ%C-LF5ka-c7KJ}Y1nTz*L&;tPVoJU)ei_So)_0Y+&dpU6u!98TR)G5ulz@E z|2)UHEqV@kgIDc!oEN8!Y{?==^e<)rT!ucDLAVqp0c+g6AE7B%Hrpw4nK8|8xFE&+-1l z{sN=_qQASri~Y~}oxctFi{Siip6>G(yv~QujHrJGUT=W&J9v-xmn+}{Klc8*z1dHI z-^qOZ{=|Oc+uNSqPvdnB=jUts`v|}rum{R>h zI6r%3KQ`7c3fQv_f46>ycd4d7*R7x8T@kRphklKZ_tVR4Fl_DF?;tm<{(N|`-$CeZ zz4w%!~joZp9ff4%;=DPVsqJE-Arg$t&kN9%KO zu3vch3D{>e{ky@#Pt@Pn;&mVR*c0`4n|M76K9cOczdi##lT<%nyk5ldJzf0;@OmY< z^iuu(6ke}8h2PoNJ3qVyUb>+7{=(-4i?8`ub09HTIz3z7yJDdf1$s>#p`YG>0kEVKRy8W|4M&{ zjMpdN?L+m`#OoT)->-Yi^G*05-rwV@vp)bovmW+re`~|}8{)^;JN(?Azoj>?iM(a+u@$`c}?#! zKj6I>o_72^_>$unaQu!h!V`Dt`J3Q5$1j7gJAOHQWVq+-Z;*8S1MmaKKOE$5$@ctX z@Lk8*4-DJJ^wbmdcU53A6|FX_mAPjXZM`_7)lTB z`ENP?@t*&I+wb8$@58=PndtcdJoEQGKLft-sGi>rzBt+QJHuzDd(M6k(P#DizVPXP z>iOC5rRVniVI1E~&-vV~^c5I_`r*L{!)1QB|SeM zzMAbh`&Y!z?fDzvljrsPV))?8d;V6Af3D~JUWDo^d(M6s<@uhoAI8!JJukt-3q5DQ zjKXVrUV$$=&VCvzjkGA4kLS4*bAz_UmXl9)gEo z+jI8wNIA}a9!ri#;bq6!?_|`&%;+7XTOo6<9YbHG?_cA%h*>9!n zcoe?nIQy~G9cMq5mg5uff!Ft({aT`qC*f0$v!BbX-?{JjJiOyL z`@tmM&~x^KS#Z1n&pXb3F$Kqq@D<0|PiEC|_LC_(UWTtZ&VDl+j&H+DjJBk(!L*{>+?_$YkMarQGRInI7Y zWycfnisS5ewCy;bCDt5gKcu?j?1$8FJPSW?oc)s8jxWMHjjcH_l{LpdsyBb*P`3ii}p zqmGy0V~(?5R>JWLJncC9Y0Wv#ep-3Q>s&vMv)@+5@g~=Yp1&y?K|FqHyvlc zu9oAWL4L<*&)Lr_bZO7o&ui52C_Lsk`+ZF~9)nLh&VFEN$Jq~T&haEX?>PH~l^jpQ z%Z{_3*q-C;C)RL$p3CPr`;8qro`?G{>pA<8g&k)$Jy^}!*PCgQgxjD(Doc>KeR)~Tikw*vtQbg;~g&VTYAoZYJ-lmpIXH6 zFg)rw`>l;R9)*uP&VFnO$Jvi<%JB*KwBzj8Hsg2_KI=I9xy?Dwes1%QXW+|@v)|j6 z08cy4esMX+i}0f3>?c=toX=@@9WQhGjlH3|8MO% z`_UyGXFs~MJ zUB}t4Z_n`pm&bAT^J_cKett)eufsczv)`Y8x#wm0pyTWZ7;&8a027Ya;IodiU*NLi z`|vHt*-voCarP6eJKpB{yu9b^H#q3H|19hejJc+zoy7~^w11YdDH9JbF}k39mfIUa@A9Up}!-qG_IJmvTVJnwh{zV3JuzTtQZ zzUg=xzT+p=@CHR8lWq8%` z3f%v$p7U9Gc(vy>_>|*yc-HZKu0O|{@RH*#_?F{s_@3h(_<`g8+hTuvch5ucDaXU` z1;-=sRmY?7qT{3Rb;o1y4aX&pBR$=N+$e{v6-u z`gObs-*UVKuR7kot@V#N_73OQasTabK6E?;?>HWYM~Xd77QF6woAc**2Y%$Z z|Mr;Q5A-|)A96elA9g$fA8|YiA9s8dKIwQ2KIQlXe9rL%e8KS~e97??eAV$ZyyAEU zUUfVRuQ@&sKX7~z9$xEtp7ZZ`0UmdJ1wQR~k@MsDI(*yl5`5qBGQ9101s?j>o^QjW zj@RH5j@RKcj_JhNm2lz?U44!pn}2 z!Yhu);8n*b;MF=yybWn-gbN*-f?^p?*F%*=iy1m3-Bq& zSK!l*7vU?8ufx|JFTr;lFT)#-SKvpEZ^NVOJ+E|)j_=4k6_=e-7@NLIq@S5Wj@Ves(_<`d|c*pS+ zeB#4BPs3*%&%m>eXW@Cr=iyby7dbzU=ix2K3-Ez|@A(RR#PK3L;rKdy+3^y5-|;fX z?|20s+UWTDM9KVi-;7!NF z@I%KV@Q&kA_~3u^d=x(Fcnm)7_yj!RcmkesJPA)bo`Po_Ps6j0XW(;=XW@&E&%>7- zU%aFBS3LGSe9iF!e8ce-c+K%5eBbePc+2q;*N@|6c<3WNufQXYZ*zS)UV~3KUWX?g z--pjQ-sJK--h$^GZ^M@z@4!or`|pJFiQ^&op5tM7=%YQ4z~hcb;d73U!q*&+!E26B zz;_)_!1os)@v_qn_u>v|)%Z)e8wBz)HK6nw$) zGSfz;X6H4Le@q@;Y9IM;))g zM;+gW#~iQ0XB=;F{W;!-&pF=V`gGiXS8Q*`L-2y*Vfd=!5%`+p zQFz1gQF!E2J&(boj!(cx9Z$f=9Z$mJj;G+0j;G;Mj%VO$$FuN^AzmgwG1^Bz#VIKjD$^rG%%#R}yZ8uO|Jd`9?G!e?E637-?b zp72QcM#59!Hxh1zZzues@LLIA5#r!qbFr2=6ESy6~lh zZwg;Y__oVGVfWd;Hxs_=)-U0E!o6>;`Mz7fgdYfRCj3zNbi$8Z{s|vCCiy0OSomtf zM}%KZ_^9yBgpUcomGBAS`w45|M+u)4e)8LEJ|%oS;WNS~6Fw_^DdBT2zl29Fzl5hQ zzl2+tU&1fC{1Uz-{DXuq3m^WgHD48eI^k==I^pZWrxU&*d@kYFg_jB6bo-O=ZQ+*_ zz9W1i;k&}O6TT<>cEb0CA0+%h_|WY&KNLQbu>0)!ClWsNLD6r*hlSgOj|lH4d{p>S z!pDTKCVWEpTEbfR?SxMXANlJwpAtTm@EPGz!e@nd5sOijqrOJ^6$M5y7#d+4nBYWj_@1FeBTwmmGFNGznSp=xb;Z*k?`TaUGv5>a=u9T zUBWuyCxmUnPYRz*_@|!f9sJ|=$9zEZ=}25<9M$u%K2y9`&AqM_k|trcl!U1+rN*7&nvt3&k2A33mg7> zX&hha^#5{)|0Ln}$bWw(eCzWY{`+6t_^;7^#J4}uyVV*0W{3Ylc=<;g{`1go{J(VC z-x2=7FNM#myY~MQe)Po+e@n%2??aFGf0tvac6xY^9I+=m?LX7u_jULK9sY$5Z+6%S zyWe(sr5Ez~l}`Jw2|xek4gY&MuKiP;_TLmfD(AOXX-GFn$KMk^F8X*G{$VHnq2rJ96T()G@ALHk*-rcWJN%Ij7sBo{ zvY%%EP71qskmCA2*XjQo!Vf+gz8}c7Ki_E|9}mA(bC&TKu&L>*LU}>3m<>~I^VB$;(guaTlM_!Il1<4ciR8% zc=#>3v&8>L;m`bA_`U?k_l}3}uDA{VduROjI{e?qgO}a+);T}_u+x6%!(m&(N&8Rs z4uAOZ_V)^Z;tw|b?+{Vgg|8;#&k5i8O89;h$LBlwtUCOA9ezpp%pZpD6Ywh zc>B)@ACmLSQQCWZ)7@u>^8fyYdeux8bGJF2G_9{%Oh&F;?0Q@cMw5jb&>!v2mVTpI z?X4zl%{JBj`GxgXQ@3GbJ8Z1#3zPZSh3U_l?P-0Xp1SSjYBF#8qk6fjhXWr_rfci| zYy~ZMF81U0R?~#UWTQVD?7Pk3&R{+dv4*>={%qJVvrEOdHp_b0#I6q9b}ONLxxd_7 z9c*N7OA-zw>oJ@7ScA5$=V33l{T>X4Y;7+m3zlgxTaI@7ZOAY{Q_n~J!DzHK=+uqs zX{fs}SRE|)Xz5mBelc!K$K^tn$1lTlxZD}7;`%HHtHI2{UcGGELA%?qn6ts^V*h;Y zW5~qP?1#+Qkd`LwzF&pCrXKd&IvjOb)Zuu$&xDi31-F~*txu^Q?6y1o)xk(#E(d*A z?Y3p%`^(vRzd0QE^_s*Dx9;o1GOydc#p=9IWu5-P5sNzH*fx?=f4JD4w=2J2?f}WL zUe%(UbhhaH)m)l|^uj1|5B5bVCpqIF8_XqRnH&Ml4wH;Pv+$3uxN2gwm z>y;0%7>}om!Kgo+EyKumQTx8W>&~KSC;q4pR?Btu-l*|MZMB%z{l#?DtxNW@@BJ{V z2hHxP7VW>_SHkJ{h22S5G*83EYk4(ueRh$Pr{!YR#$^V|`9JT1#UGgG@io{Sg$=C}PG>`(mS zuO?xQM7H(Z&%3v9=uUsDc~6egd@!qfvIseNvLm4(|dh3;*?@p)v@pQ1=Je&8ncE>$`A&~u?%(wG+8g#qvce!pC zgTC~7RwqZ%jq(Yvn))$o%c3rpt-H)kmT{nRE$;l}q!=!1VPHGG(0JS$hGkndl44D3 zJbqM;>Y>=VFE$ScIaa$B_a`)Wt@2~Sa8AS=P!bN88xhiW9d>bDIasX*7uS_9jJCpR zda2F!+_tL|8u}zI_6J*Aa&VzQqCQic?z)S=AbGNX)4 zd#NZ3O5&7;(o$BTG{iBRl*BW{F~l{*GsH8*GsH8*v&6B)wZyZ;v&5^Yuc)tLJ>x6J zSIisN#m0G<*OG^g?Xf@g75%C(E(^y@%1z3QQd5R}vaEnhIJR3#+OybB9FA9(5kDi| zW}M$p59jpD8K1}Tu^;p0#L3AcXa1aiIeFytS1~U0DB>&PE8;2Q=~z!(O}nOD5nsjl z#MR8BV|?<_F%IK&tY^Gte8KpF`3m9`bo0hA%Swkl~LE-(>hB!yg&G$nZ&qKQjE0q5BNoXXrFT|5+6|%$r9&+BlwhZOn@j zUFT89HpXKdzRK`VhQG2Z#*cZ&_%ROc_%O#WIeO3WMXqALCH0i(J4gRH`p@x2j!*K< zIG+7LmpQu3(PggUe8feEIXcYq$jpb%^DMT*_$J3kIX=ttm?!z`+Z=u7=rc#3Il9cz zWnRX3#K#{we#y%iH|7`fWnTQ37jb`J9rI!wzR1yAj{bA>ouj)P{pL3ICm-~fM?K<$ zyo&XVL-#p;%F%s}?sNQ*;~Rxwx0ApwPcU?+TqO^sCUjLe~nNEA+3> zzd|<(AE_*kkK>4opA`C3=vbj!g^m@vR(b4CTy(3@twOg7pD6sM@SDPK3co3QrtqD@ zZwlWlbgj_4!Uqc7EA+1Lg+liVohWpo@PWby3Lhx+rO=zg2MT{Ebf=0qo_X+%LbnPX zt1{Lz9^ET^pzxK#M+#pl{G?1APhRL+;V)(4eB_JYl!^UgJ@L`KLiY-tD|D~$fxexGpICpwO{K*9x6$^sLdbM%NlWYjm&Cvqs+gM@S)bRp8n`s zmoXmW(XB?`8og^1*Ngm2j1&8lFaFW!T%&W1zBPK*=vbq3jlMPd*XUcLZ;ie+`qrGk zbrs_gpX-6<{I5B`YtH|g^S|c0P~eLq>OJ}epA`6{z#j#EDey^wFN)0=FOCaw3Vc!E zivr&i_@clM1%4>-LxHaf{7~d^9P^{s0-qG^g&~u^U_{j7_ zj|F<-ukgamkFE-IRiN7f-4^JzK)(e(E%0rDUyCBP(;uI5TR=+YL-z%`=YD~dj7P@> zx-8Ilfo=D9~|%jtkD$1$r*fYk__XbX}nH0{s@~m)j#!G9JAa z=(s?)1-dP&7>|5xY=_Zx5%nB(i;lUGB4tLIQz}YLSx}agAx@dae#AqU+>6P$86zd* z(PfDq%PhuWJbEoTua|3 z;wSEPW!(Cbk~rwTMEBeblag^J_9HKJU!uFxMrL00TB6euJ(lROv~j-3^hduXekt)w ziJwXv`;$i%{c~qf`q7R*48Ab< zf?J1D5+D5=^v^v-Dd~?N41O^9#^4Ks9}Idm_<@^}QW6JW7<6pVxk2CDy_AwT_{88N zgWe5#H|X1-Z-ed)Iyd;l;0uH94Z1Yw-JpMiP7OLW=+mH2gKiD}F!;mZ4}%X3*8ziH z41O_O2MoS3_{HECgC7mo0fQe5elYmK;0JE=N=ZEYV9>L{CkEXb^ls3(LFWdY8+2~) zlfh30y&Lpy@RvdN2A>&pZt$By?*`wQsC)cp@Q1-K7X4d%Vey5<4;DXI{9y5eMei29 zTl8-6gGKii-CO)((Z9txDh=MP%aQ6N^tQ zKC$@2;tz{&EdH?g#o`OA<9OoYAB$cs{;>GN;t#81JMr;}#U~b@SbSpfiNz-tpYWVP z${08Hi+K>Qj3sf=w?*F;U0ZZ*(X~a_7F}C(ZPB$w*A`t{bZybKMb{Qx^CU#_Vm!XJ z_?8DIQqsSS^T&Gfz}L2n@u|lr7N1!BVey5<4;DXId}Hy8#a9-eSbSpf36F53%qVk8 zMX4zZ%97GhT1w*KlM0_y_@u%o6+Wr(2~UfpBpyDg@JWSFDty9YB`JxAPbz%E^Cl^Y zhd(O(QQ?mYe^mIR!UsI4%6L*GCGpT;2X}SMMEU=%2&)cIG1=z2_gtjwQm#y-n5MUiL?m zX6eU<_X_5&dw7uT_G?zpW{V4TubDH__1v1Y{*iaD-ygOYmvw*3jo7L8{nL2g!#x>y zuTG4&>$dS#zNd@lQeVnKE>>=bnqIq@`uB*&^ps8X2Xp?1>BO;+fPGsU5lNTR+LXwOx zWl8*eA-}z8d^;=&=2kAWjTfugpbf7|Nm7FmFL{vBc(JU58YatdIAy4N*gqSDcdY#D z605FqF>|U ZkV06+^)X+pWNGSAIQDYXLYvR#{{f1fv>N~b literal 0 HcwPel00001 -- 2.11.4.GIT