# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1116 -> 1.1320 # drivers/net/3c59x.c 1.19 -> 1.20 # include/net/route.h 1.7 -> 1.15 # net/ipv4/syncookies.c 1.7 -> 1.10 # include/linux/sysctl.h 1.22 -> 1.23 # net/ipv4/ip_forward.c 1.2 -> 1.9 # net/ipv4/raw.c 1.7 -> 1.17 # net/ipv6/tcp_ipv6.c 1.21 -> 1.30 # net/ipv6/af_inet6.c 1.9 -> 1.11 # arch/cris/config.in 1.13 -> 1.14 # include/linux/skbuff.h 1.15 -> 1.18 # include/net/dn_route.h 1.1 -> 1.2 # net/ipv6/ndisc.c 1.20 -> 1.24 # net/ipv6/exthdrs.c 1.4 -> 1.7 # net/ipv4/ipconfig.c 1.18 -> 1.19 # net/ipv6/ip6_output.c 1.11 -> 1.17 # net/ipv4/netfilter/ipt_MASQUERADE.c 1.5 -> 1.6 # net/ipv4/ip_input.c 1.5 -> 1.10 # arch/sparc/config.in 1.14 -> 1.15 # net/ipv6/ipv6_sockglue.c 1.8 -> 1.10 # net/ipv4/Config.in 1.3 -> 1.8 # net/ipv6/datagram.c 1.5 -> 1.6 # arch/s390x/config.in 1.9 -> 1.10 # Makefile 1.207 -> 1.208 # include/linux/inetdevice.h 1.4 -> 1.5 # include/net/tcp.h 1.21 -> 1.23 # include/linux/ipsec.h 1.2 -> 1.4 # net/ipv4/protocol.c 1.3 -> 1.4 # net/ipv4/af_inet.c 1.10 -> 1.15 # net/ipv4/netfilter/ip_nat_core.c 1.17 -> 1.18 # net/ipv4/udp.c 1.9 -> 1.19 # net/ipv6/protocol.c 1.2 -> 1.3 # include/asm-ppc/kmap_types.h 1.8 -> 1.11 # net/ipv4/fib_semantics.c 1.6 -> 1.7 # net/core/skbuff.c 1.9 -> 1.12 # arch/arm/config.in 1.21 -> 1.22 # net/ipv6/ip6_input.c 1.2 -> 1.9 # net/ipv6/route.c 1.14 -> 1.22 # net/ipv4/tcp_input.c 1.23 -> 1.24 # net/ipv4/tcp_minisocks.c 1.13 -> 1.14 # include/asm-sparc/kmap_types.h 1.6 -> 1.9 # include/net/ip6_route.h 1.3 -> 1.5 # arch/alpha/config.in 1.22 -> 1.23 # net/Config.in 1.10 -> 1.12 # include/linux/udp.h 1.1 -> 1.4 # net/ipv4/devinet.c 1.8 -> 1.10 # arch/ppc64/config.in 1.5 -> 1.6 # net/ipv4/Makefile 1.3 -> 1.10 # net/ipv4/netfilter/ip_fw_compat_masq.c 1.4 -> 1.5 # arch/s390/config.in 1.9 -> 1.10 # net/ipv6/ip6_fib.c 1.7 -> 1.8 # include/net/ipv6.h 1.5 -> 1.6 # net/ipv4/tcp.c 1.25 -> 1.27 # net/ipv6/udp.c 1.9 -> 1.16 # net/ipv4/netfilter/ipt_REJECT.c 1.10 -> 1.12 # include/linux/ip.h 1.1 -> 1.4 # net/sched/cls_route.c 1.4 -> 1.5 # net/ipv4/ip_sockglue.c 1.6 -> 1.10 # net/ipv6/icmp.c 1.14 -> 1.18 # arch/sparc64/config.in 1.25 -> 1.26 # include/linux/netlink.h 1.7 -> 1.9 # net/ipv6/reassembly.c 1.6 -> 1.8 # net/ipv4/arp.c 1.10 -> 1.12 # arch/i386/config.in 1.41 -> 1.42 # net/ipv4/tcp_ipv4.c 1.20 -> 1.29 # include/net/flow.h 1.1 -> 1.3 # include/net/ip_fib.h 1.2 -> 1.4 # include/net/raw.h 1.2 -> 1.3 # net/ipv4/icmp.c 1.16 -> 1.21 # net/ipv6/raw.c 1.10 -> 1.13 # include/net/ip6_fw.h 1.1 -> (deleted) # include/linux/netdevice.h 1.24 -> 1.26 # net/netsyms.c 1.35 -> 1.53 # include/net/protocol.h 1.4 -> 1.9 # net/Makefile 1.6 -> 1.9 # include/net/rawv6.h 1.2 -> 1.3 # net/atm/clip.c 1.4 -> 1.5 # net/ipv4/netfilter/ip_conntrack_standalone.c 1.10 -> 1.11 # net/core/netfilter.c 1.7 -> 1.8 # net/ipv6/ip6_fw.c 1.2 -> (deleted) # net/ipv4/fib_frontend.c 1.7 -> 1.8 # net/ipv4/ipmr.c 1.8 -> 1.14 # net/ipv4/fib_hash.c 1.2 -> 1.3 # net/ipv6/Config.in 1.3 -> 1.5 # include/linux/in.h 1.1 -> 1.4 # include/net/transp_v6.h 1.1 -> 1.2 # net/netlink/af_netlink.c 1.10 -> 1.11 # net/ipv4/ipip.c 1.13 -> 1.22 # net/core/dev.c 1.34 -> 1.35 # arch/sh/config.in 1.8 -> 1.9 # arch/ia64/config.in 1.17 -> 1.18 # net/core/rtnetlink.c 1.5 -> 1.6 # net/ipv4/netfilter/ipt_TCPMSS.c 1.5 -> 1.7 # arch/mips/config-shared.in 1.2 -> 1.3 # arch/ppc/config.in 1.30 -> 1.31 # net/ipv4/fib_rules.c 1.3 -> 1.4 # MAINTAINERS 1.99 -> 1.100 # net/core/dst.c 1.3 -> 1.6 # include/linux/in6.h 1.4 -> 1.5 # lib/Config.in 1.1 -> 1.2 # net/ipv4/tcp_output.c 1.15 -> 1.17 # include/net/ip.h 1.2 -> 1.5 # arch/x86_64/config.in 1.4 -> 1.5 # include/linux/ipv6.h 1.1 -> 1.3 # include/asm-i386/kmap_types.h 1.6 -> 1.9 # include/net/sock.h 1.15 -> 1.20 # arch/m68k/config.in 1.16 -> 1.17 # net/ipv4/sysctl_net_ipv4.c 1.8 -> 1.9 # include/net/ip6_fib.h 1.2 -> 1.3 # net/ipv4/ip_gre.c 1.8 -> 1.16 # net/ipv6/Makefile 1.2 -> 1.8 # net/ipv4/ip_nat_dumb.c 1.2 -> 1.4 # include/linux/rtnetlink.h 1.6 -> 1.7 # Documentation/Configure.help 1.177 -> 1.193 # net/ipv6/sit.c 1.12 -> 1.17 # include/net/dst.h 1.1 -> 1.12 # net/decnet/dn_route.c 1.6 -> 1.9 # include/net/ipip.h 1.2 -> 1.3 # include/asm-x86_64/kmap_types.h 1.3 -> 1.6 # net/decnet/dn_nsp_out.c 1.2 -> 1.3 # net/ipv4/igmp.c 1.7 -> 1.12 # net/ipv4/ip_output.c 1.12 -> 1.21 # net/ipv4/route.c 1.21 -> 1.31 # arch/parisc/config.in 1.5 -> 1.6 # net/ipv4/netfilter/ipt_MIRROR.c 1.3 -> 1.4 # (new) -> 1.7 net/ipv6/xfrm6_input.c # (new) -> 1.2 net/xfrm/Makefile # (new) -> 1.14 crypto/Makefile # (new) -> 1.11 crypto/des.c # (new) -> 1.1 Documentation/crypto/descore-readme.txt # (new) -> 1.2 crypto/serpent.c # (new) -> 1.8 net/xfrm/xfrm_algo.c # (new) -> 1.6 crypto/md4.c # (new) -> 1.13 net/ipv6/esp6.c # (new) -> 1.14 crypto/Config.in # (new) -> 1.3 net/ipv4/ipcomp.c # (new) -> 1.23 net/xfrm/xfrm_policy.c # (new) -> 1.2 crypto/crypto_null.c # (new) -> 1.3 crypto/aes.c # (new) -> 1.21 crypto/tcrypt.c # (new) -> 1.10 net/xfrm/xfrm_input.c # (new) -> 1.28 net/ipv4/esp.c # (new) -> 1.12 Documentation/crypto/api-intro.txt # (new) -> 1.3 crypto/hmac.c # (new) -> 1.2 crypto/twofish.c # (new) -> 1.28 net/key/af_key.c # (new) -> 1.3 net/ipv4/xfrm4_policy.c # (new) -> 1.3 crypto/blowfish.c # (new) -> 1.9 crypto/sha1.c # (new) -> 1.8 crypto/md5.c # (new) -> 1.2 net/ipv6/xfrm6_state.c # (new) -> 1.26 crypto/api.c # (new) -> 1.7 crypto/compress.c # (new) -> 1.13 net/ipv6/ah6.c # (new) -> 1.2 net/ipv4/xfrm4_state.c # (new) -> 1.3 net/ipv4/xfrm4_tunnel.c # (new) -> 1.1 include/asm-sparc64/kmap_types.h # (new) -> 1.7 include/linux/xfrm.h # (new) -> 1.1 crypto/sha512.c # (new) -> 1.17 net/xfrm/xfrm_user.c # (new) -> 1.13 crypto/tcrypt.h # (new) -> 1.3 crypto/deflate.c # (new) -> 1.15 crypto/digest.c # (new) -> 1.21 net/ipv4/ah.c # (new) -> 1.6 crypto/autoload.c # (new) -> 1.23 net/xfrm/xfrm_state.c # (new) -> 1.2 include/net/esp.h # (new) -> 1.2 crypto/sha256.c # (new) -> 1.1 net/key/Makefile # (new) -> 1.1 net/ipv6/ipv6_syms.c # (new) -> 1.5 include/linux/pfkeyv2.h # (new) -> 1.3 crypto/proc.c # (new) -> 1.27 include/linux/crypto.h # (new) -> 1.16 crypto/internal.h # (new) -> 1.2 include/net/ah.h # (new) -> 1.14 crypto/cipher.c # (new) -> 1.31 include/net/xfrm.h # (new) -> 1.3 net/ipv6/xfrm6_policy.c # (new) -> 1.1 net/xfrm/Config.in # (new) -> 1.3 net/ipv4/xfrm4_input.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1117 # [CRYPTO]: Add initial crypto api subsystem. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1118 # [CRYPTO]: Cleanups based upon feedback from Rusty and jgarzik # - s/__u/u/ # - s/char/u8/ # - Fixed bug in cipher.c, page remapped was off by one block # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1119 # [CRYPTO]: Cleanups based upon feedback from Rusty and jgarzik # - s/__u/u/ # - s/char/u8/ # - Fixed bug in cipher.c, page remapped was off by one block # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1120 # [CRYPTO]: Use try_inc_mod_count and semaphore for alg list. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1121 # [CRYPTO]: Use kmod to try to autoload modules. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1122 # [CRYPTO]: Bug fixes and cleanups. # - try_inc_mod_count() already does what crypto_alg_get() was trying to do. # (feedback from Andrew Morton.) # - Moved the BUG_ON() in crypto_unregister_alg() further up, no need to # bother iterating over the list. # - Always use kmap_atomic (feedback from Andrew Morton). Implemented two # atomic kmaps, KM_USER for user context and KM_SOFTIRQ for softirq # context. # - Fixup KM_CRYPTO_ placement so Dave does not go crazy. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1123 # [CRYPTO]: More bug fixes and cleanups. # - added back USAGI copyright for HMAC (lost earlier during some # refactoring). # - bugfix: make sure tfm pointer is set to NULL during post allocation # failure path in crypto_alloc_tfm() # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1124 # [CRYPTO]: Add MD4. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1125 # [CRYPTO]: Algorithm lookup API change plus bug fixes. # - API change: implemented simplest version of algorithm lookup # by name (feedback from Rusty Russell and Herbert Valerio Riedel). # - Now need to add the following line to to /etc/modules.conf for # dynamic module loading: # alias des3_ede des # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1126 # [CRYPTO]: Run tcrypt through lindent, plus doc update. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1127 # [CRYPTO]: Assert that interfaces are called on correct cipher type. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1128 # [CRYPTO]: Cleanups and more consistency checks. # - Removed local_bh_disable() from kmap wrapper, not needed now with # two atomic kmaps. # - Nuked atomic flag, use in_softirq() instead. # - Converted crypto_kmap() and crypto_yield() to check in_softirq(). # - Check CRYPTO_MAX_CIPHER_BLOCK_SIZE during alg init. # - Try to initialize as much at compile time as possible # (feedback from Christoph Hellwig). # - Clean up list handling a bit (feedback from Christoph Hellwig). # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1129 # [CRYPTO]: Update to IV get/set interface. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1130 # [CRYPTO]: kunmap does not return a value. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1131 # [CRYPTO]: Build/warning fixups. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1132 # [CRYPTO]: Add some documentation. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1133 # [CRYPTO]: Clean up header file usage. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1134 # [CRYPTO]: Fix some credits. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1135 # [CRYPTO]: Cleanups based upon suggestions by Jeff Garzik. # - Changed unsigned to unsigned int in algos. # - Consistent use of u32 for flags throughout api. # - Use of unsigned int rather than int for counting things which must # be positive, also replaced size_ts to keep code simpler and lessen # bloat on some archs. # - got rid of some unneeded returns. # - const correctness. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1136 # [CRYPTO]: Uninline some functions to save some bloat. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1137 # [CRYPTO]: Cleanups based upon feedback from jgarzik. # - make crypto_cipher_flags() return u32 (this means it will return # the actual flags reliably, instead of being just a boolean op). # - simplify error path in crypto_init_flags(). # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1138 # [CRYPTO]: Add crypto_alg_available interface. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1139 # [CRYPTO]: Rework HMAC interface. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1140 # [CRYPTO]: Include kernel.h in crypto.h # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1141 # [CRYPTO]: Allocate work buffers instead of using kstack. # -------------------------------------------- # 03/04/18 torvalds@transmeta.com 1.1142 # The crypto auto-load should be enabled if crypto is enabled. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1143 # [CRYPTO]: Add SHA256 plus bug fixes. # - Bugfix in sha1 copyright # - Add support for SHA256, test vectors and HMAC test vectors # - Remove obsolete atomic messages. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1144 # [CRYPTO]: Add blowfish algorithm. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1145 # [CRYPTO]: Make sha256.c more palatable to GCCs optimizers. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1146 # [CRYPTO]: minor updates # - Fixed min keysize bug for Blowfish (it is 32, not 64). # - Documentation updates. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1147 # [CRYPTO] kstack cleanup (v0.28) # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1148 # [CRYPTO] Add maintainers entry. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1149 # [CRYPTO] Minor doc update. # -------------------------------------------- # 03/04/18 jgarzik@redhat.com 1.1150 # [CRYPTO]: Kill accidental double memset. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1151 # [CRYPTO]: Add null algorithms and minor cleanups. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1152 # [CRYPTO]: Kill stray CRYPTO_ALG_TYPE_COMP. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1153 # [CRYPTO]: Add twofish algorithm. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1154 # [CRYPTO]: Add serpent algorithm. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1155 # [CRYPTO]: Documentation update. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1156 # [CRYPTO]: Dont compile procfs stuff if procfs is not enabled. # -------------------------------------------- # 03/04/18 adam@yggdrasil.com 1.1157 # [CRYPTO]: Simplify crypto memory allocation. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1158 # [CRYPTO]: internal.h needs init.h # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1159 # [CRYPTO]: Add AES algorithm. # - Merged AES code from Adam J. Richter # - Add kconfig help and test vector code from # Martin Clausen # - Minor cleanups: removed EXPORT_NO_SYMBOLS (not needed for 2.5), # removed debugging code etc. # - Documentation updates. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1160 # [CRYPTO]: Use appropriate defaults if AH/ESP is enabled. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1161 # [CRYPTO]: More credits for AES. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1162 # [CRYPTO]: Add support for SHA-386 and SHA-512 # - Merged SHA-384 and SHA-512 code from Kyle McMartin # # - Added test vectors. # - Documentation and credits updates. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1163 # [CRYPTO] remove superfluous goto from des module init exception path # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1164 # [CRYPTO] Add AES and MD4 to tcrypto crypto_alg_available() test. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1165 # [CRYPTO]: in/out scatterlist support for ciphers. # - Merge scatterwalk patch from Adam J. Richter # API change: cipher methods now take in/out scatterlists and nbytes # params. # - Merge gss_krb5_crypto update from Adam J. Richter # - Add KM_SOFTIRQn (instead of KM_CRYPTO_IN etc). # - Add asm/kmap_types.h to crypto/internal.h # - Update cipher.c credits. # - Update cipher.c documentation. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1166 # [CRYPTO]: Move km_types out of header. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1167 # [CRYPTO]: Add encrypt_iv() and decrypt_iv() methods. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1168 # [CRYPTO]: Eliminate crypto_tfm.crt_ctx, from Adam Richter. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1169 # [CRYPTO]: Documentation updates. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1170 # [CRYPTO-2.4]: Add dummy kmap_types.h header for sparc64. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1171 # [CRYPTO]: Include linux/errno.h as appropriate. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1172 # [CRYPTO-2.4]: module_name does not exist in 2.4.x # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1173 # [CRYPTO]: Make use of crypto_exit_ops() during crypto_free_tfm(). # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1174 # [CRYPTO]: Add Deflate algorithm to crypto API. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1175 # [CRYPTO]: deflate module: workaround zlib bug. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1176 # [CRYPTO-2.4]: const static --> static const. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1177 # [CRYPTO]: deflate.c needs slab.h # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1178 # [CRYPTO-2.4]: Fix condition typos in crypto/Config.in # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1179 # [IPV4/IPV6]: Cleanup inet{,6}_protocol. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1180 # [IPV4]: Use generic struct flowi as routing key. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1181 # [NET]: Ipv4 output path changes by Alexey. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1182 # [IPV4]: Provide full proto/ports in flowi route lookups. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1183 # [IPV4]: Kill ip_send, use dst_output instead. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1184 # [NET]: Kill reroute from DST ops, unused. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1185 # [IPV4]: Missing ip_rt_put in ip_route_newports. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1186 # include/linux/ip.h: Define AH/ESP header layout. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1187 # [NET]: Fix rtnetlink metric type, should be u32. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1188 # [NET]: Cleanup DST metrics and abstract MSS/PMTU further. # - Changed dst named metrics, to RTAX_MAX metrics array. # - Add inline shorthands to access them # - Add update_pmtu and get_mss to DST ops. # - Add path component to DST, it is DST itself by default. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1189 # [NET]: Add DST_NOXFRM and DST_NOPOLICY flags. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1190 # net/ipv4/route.c: Create compare_keys to compare flowi identities. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1191 # [IPV4]: Rework key route lookup interface slightly. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1192 # [IPSEC]: Add transform engine and AH implementation. # -------------------------------------------- # 03/04/18 viro@math.psu.edu 1.1193 # [NET]: Compile fixes. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1194 # [IPV4]: Define IPPROTO_SCTP. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1195 # [UDP]: Delete buggy assertion. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1196 # [NET]: Some missed cases of dst_pmtu conversion. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1197 # [NET]: IPSEC updates. # - Add ESP tranformer. # - Add AF_KEY socket layer. # - Rework xfrm structures for user interfaces # - Add CONFIG_IP_{AH,ESP}. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1198 # [IPSEC-2.4]: Fix inet_getid invocation for 2.4.x # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1199 # [IPSEC]: Fix xfrm policy locking. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1200 # [AF_KEY]: Convert to/from IPSEC_PROTO_ANY. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1201 # [IPSEC]: XFRM policy bug fixes. # - Fix dst metric memcpy length. # - Iterator for walking skb sec_path goes in wrong direction. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1202 # [IPSEC]: Bug fixes and updates. # - Implement IP_IPSEC_POLICY setsockopt # - Rework input policy checks to use it # - dst->child destruction is repaired # - Fix tunnel mode IP header building. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1203 # [IPSEC]: Export xfrm_policy_list. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1204 # [IPSEC]: Allocate work buffers instead of using kstack. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1205 # [IPSEC]: RAWv4 makes inverted policy check. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1206 # [IPSEC]: Semantic fixes with help from Maxim Giryaev. # - BSD apps want sin_zero cleared in sys_getname. # - Fix protocol setting in flow descriptor of RAW sockets # - Wildcard protocol is represented differently in policy # than for association. # - Missing update of key manager sequence in xfrm_state entries. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1207 # [IPSEC]: Few changes to keep racoon ISAKMP daemon happy. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1208 # [IPSEC] More work. # 1. Expiration of SAs. Some missing updates of counters. # Question: very strange, rfc defines use_time as time of the first use # of SA. But kame setkey refers to this as lastuse. # 2. Bug fixes for tunnel mode and forwarding. # 3. Fix bugs in per-socket policy: policy entries do not leak but are destroyed, # when socket is closed, and are cloned on children of listening sockets. # 4. Implemented use policy: i.e. use ipsec if a SA is available, # ignore if it is not. # 5. Added sysctl to disable in/out policy on some devices. # It is set on loopback by default. # 6. Remove resolved reference from template. It is not used, # but pollutes code. # 7. Added all the SASTATEs, now they make sense. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1209 # [IPSEC]: Fix lockup in xfrm4_dst_check. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1210 # [IPSEC]: More fixes and corrections. # - Make connect() policy selection actually happen # - return len instead of 0 on successful pfkey sendmsg # - make prefixlen checks in a way more compatible with isakmpd # - key manager wait queues are totally wrong # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1211 # [IPSEC]: Make netlink user interface header. # -------------------------------------------- # 03/04/18 viro@math.psu.edu 1.1212 # [ipt_TCPMSS]: Compile fix. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1213 # [UDP]: silly bug, local input policy did not work on udp sockets. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1214 # [IPSEC]: ah/esp, 0 was used as tunnels protocol. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1215 # [IPSEC]: authentication signature for MD5/SHA was not truncated to conform RFC. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1216 # [AF_KEY]: Fix alloc_skb args. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1217 # [IPSEC]: More pfkey2 semantic fixes. # - xfrm_state.c: never return mature SAs on getspi. # - af_key.c: do not forget to delete dummy super-larvals when they are resolve\d # - af_key.c: wow! specially for this case I added gfp argument # to xfrm_alloc_policy() and forgot to use it really. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1218 # [IPSEC]: Netlink configuration interface. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1219 # [XFRM_USER]: Destroy netlink socket on shutdown. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1220 # [XFRM]: Add family member to state/policy structs. # -------------------------------------------- # 03/04/18 taral@taral.net 1.1221 # [IPSEC]: Fix double unlock in esp/ah. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1222 # [IPSEC]: Policy timeout and pfkey acquire fixes. # - Implement policy timeouts. # - Make PF_KEY return proper error from KM acquire. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1223 # [IPSEC]: Make xfrm_user key manager return proper errors. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1224 # [XFRM_USER]: Index xfrma array correctly. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1225 # [PATCH] IPv6: Fix BUG When Received Unknown Protocol. # -------------------------------------------- # 03/04/18 hch@lst.de 1.1226 # [AF_KEY]: Fix comment typo. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1227 # [NET]: Protect skbuff secpath code with CONFIG_INET. # -------------------------------------------- # 03/04/18 akpm@digeo.com 1.1228 # [IPSEC]: Uninline _decode_session. # -------------------------------------------- # 03/04/18 akpm@digeo.com 1.1229 # [IPV4 OUTPUT]: Uninline ip_finish_output and skb_fill_page_desc. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1230 # [IPSEC]: Clean up key manager algorithm handling. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1231 # [IPSEC]: Dont check algorithm availability unless CONFIG_CRYPTO. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1232 # [IPSEC]: Kill warning in xfrm_algo.c. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1233 # [IPSEC]: Clear SKB checksum state when mangling. # -------------------------------------------- # 03/04/18 thomas@bender.thinknerd.de 1.1234 # [IPSEC]: Fix some buglets in xfrm_user.c # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1235 # [IPSEC]: remove trailer_len from esp and xfrm properties. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1236 # [IPSEC]: Update ah documentation. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1237 # [IPSEC] Convert esp auth to use proper crypto api calls. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1238 # [IPSEC] Generic ICV handling for ESP. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1239 # [IPSEC]: in/out scatterlist support for ciphers. # -------------------------------------------- # 03/04/18 kunihiro@ipinfusion.com 1.1240 # [XFRM]: Add family member to xfrm_usersa_id. # -------------------------------------------- # 03/04/18 latten@austin.ibm.com 1.1241 # [IPSEC]: Make AF_KEY allow NULL encryption. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1242 # [IPSEC]: Make sure to clear sin_zero in AF_KEY. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1243 # [IPSEC]: Add missed bit of sin_zero fix. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1244 # [IPSEC] Make sure SADB_X_SPDADD messages have proper spid. # -------------------------------------------- # 03/04/18 kunihiro@ipinfusion.com 1.1245 # [IPSEC]: Add ipv6 support infrastructure. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1246 # [IPSEC]: Mark pfkey_sadb_addr2xfrm_addr static again. # -------------------------------------------- # 03/04/18 kunihiro@ipinfusion.com 1.1247 # [IPSEC]: Add ipv6 support to ipsec netlink sockets. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1248 # [AF_KEY]: Add missing credit. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1249 # [NET]: Convert dst->{input,output}() fully to dst_{input,output}(). # -------------------------------------------- # 03/04/18 mk@linux-ipv6.org 1.1250 # [IPSEC]: Add missing credit and include to xfrm_user ipv6 changes. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1251 # [IPSEC]: Move xfrm6 policy code to net/ipv4/xfrm_policy.c # -------------------------------------------- # 03/04/18 latten@austin.ibm.com 1.1252 # [IPSEC]: Make sure ESP output pads Null Encryption properly. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1253 # [IPSEC]: Add family argument to compile_policy. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1254 # [IPSEC]: Use dst_hold unless assigning result to something. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1255 # [IPSEC]: Add full ipv6 support. # # Credits also to Mitsuru Kanda , # YOSHIFUJI Hideaki , # and Kunihiro Ishiguro. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1256 # [IPV4]: Fix multicast route lookups. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1257 # [IPSEC]: Fix obvious typo in xfrm_sk_clone_policy. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1258 # [NET]: hard_header reservation. # 1. Fix bad reservation in xfrm_state_check_space() # 2. Macroize formula for reservation, use the macro over all the places # in IP. # -------------------------------------------- # 03/04/18 kuznet@ms2.in.ac.ru 1.1259 # [NET]: miscellaneous fixes. # 1. Fix illegal dereference of potentially freed memory in xfrm_policy.c # 2. Complete wildcard flow addresses to real ones in xfrm_lookup(). # 3. Respect optional flag when chacking for input policy. # 4. Delete orphaned comments in ip.h. # 5. Fix mistakedly freed route in tcp connect. # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1260 # [IPSEC]: fragmentation & tcp mss calculation. # 1. Add local_df field to struct sk_buff to mark packets which # are to be fragmented locally despite of their IPv6ness of IP DF flag # 2. Add ext2_header_len to tcp_opt to keep memory of part of header length # depending on route # 3. Add trailer_len to struct dst_entry and xfrm_state to know how # much of space should be reserved at tail of frame for subsequent # transformations. # 4. [BUG] icv_trun_len must be used while mss claculation, not # icv_full_length. # -------------------------------------------- # 03/04/18 thomas@bender.thinknerd.de 1.1261 # [IPSEC]: Fix null authentication/encryption. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1262 # [IPSEC]: fix skb leak in ah and esp. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1263 # [IPSEC]: return error when no dst in ah & esp output. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1264 # [IPSEC]: Add IPV6_{IPSEC,XFRM}_POLICY socket option support. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1265 # [IPSEC]: Export xfrm_user_policy. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1266 # [IPSEC]: net/xfrm.h needs net/sock.h # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1267 # [IPSEC-2.4]: try_inc_mod_count --> __MOD_INC_USE_COUNT. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1268 # [IPSEC-2.4]: Fix ip_select_ident args in ESP/v4. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1269 # [IPSEC-2.4]: Fixup AF_KEY for 2.4.x interface differences. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1270 # [IPSEC]: Fix parsing of 16-bit ipcomp cpi. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1271 # [IPSEC]: IPV6 source address not set correctly in xfrm_state. # -------------------------------------------- # 03/04/18 jgrimm2@us.ibm.com 1.1272 # [IPSEC]: Fix SKB alloc len in ip6_build_xmit. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1273 # [IPSEC] Add initial compression support for pfkey and xfrm_algo. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1274 # [IPSEC]: Split up XFRM Subsystem. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1275 # [IPSEC]: Fix build when ipsec is disabled. # -------------------------------------------- # 03/04/18 torvalds@transmeta.com 1.1276 # Avoid warning with modern gcc's in xfrm_policy.c # -------------------------------------------- # 03/04/18 mk@linux-ipv6.org 1.1277 # [IPV6]: Process all extension headers via ipproto->handler. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1278 # [IPSEC]: Fix bug in xfrm_parse_spi() # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1279 # [IPSEC]: Make get_acqseq() xfrm_state.c:xfrm_get_acqseq(). # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1280 # [IPSEC-2.4]: Fix ipv6 xfrm exports. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1281 # [IPSEC]: Fix IPV6 UDP policy checking. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1282 # [IPSEC-2.4]: Fix module get in xfrm_policy. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1283 # [IPSEC]: Kill skb_ah_walk, not needed. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1284 # [IPSEC]: Remove duplicate / obsolete entry in include/linux/dst.h # -------------------------------------------- # 03/04/18 kuznet@ms2.inr.ac.ru 1.1285 # [IPV4]: Make sure rtcache flush happens after sysctl updates. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1286 # [IPSEC]: Remove unused field owner from selector. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1287 # [IPSEC]: linux/xfrm.h u32 --> __u32. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1288 # [IPSEC]: Missing ipv6 policy checks. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1289 # [IPSEC]: IPV6 AH/ESP fixes. # -------------------------------------------- # 03/04/18 toml@us.ibm.com 1.1290 # [IPSEC]: Use "sizeof" for header sizes. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1291 # [IPSEC]: Fix xfrm_state refcounts. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1292 # [IPSEC-2.4]: Fix xfrm/Makefile for 2.4.x # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1293 # [NET]: Use current_text_addr instead of label tricks in dst_release. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1294 # [IPSEC]: xfrm_{state,user}.c need asm/uaccess.h # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1295 # [IPSEC-2.4]: Fix net/Makefile so xfrm modules get built. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1296 # [IPSEC]: Use of "sizeof" for header sizes, part II # -------------------------------------------- # 03/04/18 derek@ihtfp.com 1.1297 # [IPSEC]: Implement UDP Encapsulation framework. # # In particular, implement ESPinUDP encapsulation for IPsec # Nat Traversal. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1298 # [IPSEC]: Store xfrm_encap_tmpl directly in xfrm_state. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1299 # [IPSEC]: Add encap support for xfrm_user. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1300 # [IPSEC]: Clean up decap state, minimize its size. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1301 # [IPSEC]: Move xfrm type destructor out of spinlock. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1302 # [IPSEC-2.4]: Use schedule_task for xfrm_state gc work. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1303 # [IPSEC]: AH/ESP forget to free private structs. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1304 # [IPSEC]: Really move type destructor out of spinlock. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1305 # [IPSEC]: Support for optional policies on input got lost. # -------------------------------------------- # 03/04/18 rusty@rustcorp.com.au 1.1306 # [IPSEC]: Avoid using SET_MODULE_OWNER. # -------------------------------------------- # 03/04/18 jef@linuxbe.org 1.1307 # [IPSEC]: Check xfrm state expiration on input after replay check. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1308 # [IPSEC]: Add initial IPCOMP support. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1309 # [IPSEC]: Add ipv4 tunnel transformer. # -------------------------------------------- # 03/04/18 jmorris@intercode.com.au 1.1310 # [IPSEC]: Fix handling of uncompressable packets in tunnel mode. # -------------------------------------------- # 03/04/18 davem@nuts.ninka.net 1.1311 # [IPV4]: xfrm4_tunnel and ipip need to privateize some symbols. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1312 # [IPV6]: Fixed multiple mistake extension header handling. # - double free if sending Parameter Problem message in reassembly code. # - (sometimes) broken checksum # - HbH not producing unknown header; it is only allowed at the beginning of # the exthdrs chain. # - wrong pointer value in Parameter Problem message. # -------------------------------------------- # 03/04/18 yoshfuji@linux-ipv6.org 1.1313 # [NET]: Use fl6_{src,dst} etc. # -------------------------------------------- # 03/04/19 davem@nuts.ninka.net 1.1314 # [IPSEC-2.4]: Missing UDP_ENCAP_ESPINUDP define. # -------------------------------------------- # 03/04/19 davem@nuts.ninka.net 1.1315 # [IPSEC-2.4]: More __ip_select_ident args fixes. # -------------------------------------------- # 03/04/19 davem@nuts.ninka.net 1.1316 # [IPSEC-2.4]: Backport synchronize_net from 2.5 # -------------------------------------------- # 03/04/19 davem@nuts.ninka.net 1.1317 # [IPSEC-2.4]: Missing bits of UDP encap changes. # -------------------------------------------- # 03/04/19 yoshfuji@linux-ipv6.org 1.1318 # [IPSEC]: nexthdr in xfrm6_input needs to be int. # -------------------------------------------- # 03/04/22 steve@gw.chygwyn.com 1.1319 # [IP_GRE]: Kill duplicate update_pmtu call. # -------------------------------------------- # 03/04/23 yoshfuji@linux-ipv6.org 1.1320 # [IPV6]: dst_alloc() clean-up. # -------------------------------------------- # diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help --- a/Documentation/Configure.help Wed Apr 23 17:09:06 2003 +++ b/Documentation/Configure.help Wed Apr 23 17:09:06 2003 @@ -5347,6 +5347,14 @@ and you should also say Y to "Kernel/User network link driver", below. If unsure, say N. +PF_KEY sockets +CONFIG_NET_KEY + PF_KEYv2 socket family, compatible to KAME ones. + They are required if you are going to use IPsec tools ported + from KAME. + + Say Y unless you know what you are doing. + TCP/IP networking CONFIG_INET These are the protocols used on the Internet and on most local @@ -5612,6 +5620,32 @@ gated-5). This routing protocol is not used widely, so say N unless you want to play with it. +IP: AH transformation +CONFIG_INET_AH + Support for IPsec AH. + + If unsure, say Y. + +IP: ESP transformation +CONFIG_INET_ESP + Support for IPsec ESP. + + If unsure, say Y. + +IP: IPComp transformation +CONFIG_INET_IPCOMP + Support for IP Paylod Compression (RFC3173), typically needed + for IPsec. + + If unsure, say Y. + +IP: IPsec user configuration interface +CONFIG_XFRM_USER + Support for IPsec user configuration interface used + by native Linux tools. + + If unsure, say Y. + Unix domain sockets CONFIG_UNIX If you say Y here, you will include support for Unix domain sockets; @@ -26494,6 +26528,98 @@ This is experimental code, not yet tested on many boards. If unsure, say N. + +CONFIG_CRYPTO + This option provides the core Cryptographic API. + +CONFIG_CRYPTO_HMAC + HMAC: Keyed-Hashing for Message Authentication (RFC2104). + This is required for IPSec. + +CONFIG_CRYPTO_NULL + These are 'Null' algorithms, used by IPsec, which do nothing. + +CONFIG_CRYPTO_MD4 + MD4 message digest algorithm (RFC1320). + +CONFIG_CRYPTO_MD5 + MD5 message digest algorithm (RFC1321). + +CONFIG_CRYPTO_SHA1 + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). + +CONFIG_CRYPTO_SHA256 + SHA256 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 256 bit hash with 128 bits of + security against collision attacks. + +CONFIG_CRYPTO_SHA512 + SHA512 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 512 bit hash with 256 bits of + security against collision attacks. + + This code also includes SHA-384, a 384 bit hash with 192 bits + of security against collision attacks. + +CONFIG_CRYPTO_DES + DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). + +CONFIG_CRYPTO_BLOWFISH + Blowfish cipher algorithm, by Bruce Schneier. + + This is a variable key length cipher which can use keys from 32 + bits to 448 bits in length. It's fast, simple and specifically + designed for use on "large microprocessors". + + See also . + +CONFIG_CRYPTO_TWOFISH + Twofish cipher algorithm. + + Twofish was submitted as an AES (Advanced Encryption Standard) + candidate cipher by researchers at CounterPane Systems. It is a + 16 round block cipher supporting key sizes of 128, 192, and 256 + bits. + + See also: + http://www.counterpane.com/twofish.html + +CONFIG_CRYPTO_SERPENT + Serpent cipher algorithm, by Anderson, Biham & Knudsen. + + Keys are allowed to be from 0 to 256 bits in length, in steps + of 8 bits. + + See also: + http://www.cl.cam.ac.uk/~rja14/serpent.html + +CONFIG_CRYPTO_AES + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + The AES specifies three key sizes: 128, 192 and 256 bits + + See http://csrc.nist.gov/encryption/aes/ for more information. + +CONFIG_CRYPTO_DEFLATE + This is the Deflate algorithm (RFC1951), specified for use in + IPSec with the IPCOMP protocol (RFC3173, RFC2394). + + You will most probably want this if using IPSec. + +CONFIG_CRYPTO_TEST + Quick & dirty crypto test module. # # A couple of things I keep forgetting: diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/crypto/api-intro.txt Wed Apr 23 17:09:06 2003 @@ -0,0 +1,221 @@ + + Scatterlist Cryptographic API + +INTRODUCTION + +The Scatterlist Crypto API takes page vectors (scatterlists) as +arguments, and works directly on pages. In some cases (e.g. ECB +mode ciphers), this will allow for pages to be encrypted in-place +with no copying. + +One of the initial goals of this design was to readily support IPsec, +so that processing can be applied to paged skb's without the need +for linearization. + + +DETAILS + +At the lowest level are algorithms, which register dynamically with the +API. + +'Transforms' are user-instantiated objects, which maintain state, handle all +of the implementation logic (e.g. manipulating page vectors), provide an +abstraction to the underlying algorithms, and handle common logical +operations (e.g. cipher modes, HMAC for digests). However, at the user +level they are very simple. + +Conceptually, the API layering looks like this: + + [transform api] (user interface) + [transform ops] (per-type logic glue e.g. cipher.c, digest.c) + [algorithm api] (for registering algorithms) + +The idea is to make the user interface and algorithm registration API +very simple, while hiding the core logic from both. Many good ideas +from existing APIs such as Cryptoapi and Nettle have been adapted for this. + +The API currently supports three types of transforms: Ciphers, Digests and +Compressors. The compression algorithms especially seem to be performing +very well so far. + +Support for hardware crypto devices via an asynchronous interface is +under development. + +Here's an example of how to use the API: + + #include + + struct scatterlist sg[2]; + char result[128]; + struct crypto_tfm *tfm; + + tfm = crypto_alloc_tfm("md5", 0); + if (tfm == NULL) + fail(); + + /* ... set up the scatterlists ... */ + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &sg, 2); + crypto_digest_final(tfm, result); + + crypto_free_tfm(tfm); + + +Many real examples are available in the regression test module (tcrypt.c). + + +CONFIGURATION NOTES + +As Triple DES is part of the DES module, for those using modular builds, +add the following line to /etc/modules.conf: + + alias des3_ede des + +The Null algorithms reside in the crypto_null module, so these lines +should also be added: + + alias cipher_null crypto_null + alias digest_null crypto_null + alias compress_null crypto_null + +The SHA384 algorithm shares code within the SHA512 module, so you'll +also need: + alias sha384 sha512 + + +DEVELOPER NOTES + +Transforms may only be allocated in user context, and cryptographic +methods may only be called from softirq and user contexts. + +When using the API for ciphers, performance will be optimal if each +scatterlist contains data which is a multiple of the cipher's block +size (typically 8 bytes). This prevents having to do any copying +across non-aligned page fragment boundaries. + + +ADDING NEW ALGORITHMS + +When submitting a new algorithm for inclusion, a mandatory requirement +is that at least a few test vectors from known sources (preferably +standards) be included. + +Converting existing well known code is preferred, as it is more likely +to have been reviewed and widely tested. If submitting code from LGPL +sources, please consider changing the license to GPL (see section 3 of +the LGPL). + +Algorithms submitted must also be generally patent-free (e.g. IDEA +will not be included in the mainline until around 2011), and be based +on a recognized standard and/or have been subjected to appropriate +peer review. + +Also check for any RFCs which may relate to the use of specific algorithms, +as well as general application notes such as RFC2451 ("The ESP CBC-Mode +Cipher Algorithms"). + +It's a good idea to avoid using lots of macros and use inlined functions +instead, as gcc does a good job with inlining, while excessive use of +macros can cause compilation problems on some platforms. + +Also check the TODO list at the web site listed below to see what people +might already be working on. + + +BUGS + +Send bug reports to: +James Morris +Cc: David S. Miller + + +FURTHER INFORMATION + +For further patches and various updates, including the current TODO +list, see: +http://samba.org/~jamesm/crypto/ + + +AUTHORS + +James Morris +David S. Miller + + +CREDITS + +The following people provided invaluable feedback during the development +of the API: + + Alexey Kuznetzov + Rusty Russell + Herbert Valerio Riedel + Jeff Garzik + Michael Richardson + Andrew Morton + Ingo Oeser + Christoph Hellwig + +Portions of this API were derived from the following projects: + + Kerneli Cryptoapi (http://www.kerneli.org/) + Alexander Kjeldaas + Herbert Valerio Riedel + Kyle McMartin + Jean-Luc Cooke + David Bryson + Clemens Fruhwirth + Tobias Ringstrom + Harald Welte + +and; + + Nettle (http://www.lysator.liu.se/~nisse/nettle/) + Niels Möller + +Original developers of the crypto algorithms: + + Dana L. How (DES) + Andrew Tridgell and Steve French (MD4) + Colin Plumb (MD5) + Steve Reid (SHA1) + Jean-Luc Cooke (SHA256, SHA384, SHA512) + Kazunori Miyazawa / USAGI (HMAC) + Matthew Skala (Twofish) + Dag Arne Osvik (Serpent) + Brian Gladman (AES) + + +SHA1 algorithm contributors: + Jean-Francois Dive + +DES algorithm contributors: + Raimar Falke + Gisle Sælensminde + Niels Möller + +Blowfish algorithm contributors: + Herbert Valerio Riedel + Kyle McMartin + +Twofish algorithm contributors: + Werner Koch + Marc Mutz + +SHA256/384/512 algorithm contributors: + Andrew McDonald + Kyle McMartin + Herbert Valerio Riedel + +AES algorithm contributors: + Alexander Kjeldaas + Herbert Valerio Riedel + Kyle McMartin + Adam J. Richter + +Generic scatterwalk code by Adam J. Richter + +Please send any credits updates or corrections to: +James Morris + diff -Nru a/Documentation/crypto/descore-readme.txt b/Documentation/crypto/descore-readme.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/crypto/descore-readme.txt Wed Apr 23 17:09:06 2003 @@ -0,0 +1,352 @@ +Below is the orginal README file from the descore.shar package. +------------------------------------------------------------------------------ + +des - fast & portable DES encryption & decryption. +Copyright (C) 1992 Dana L. How + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 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 Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Author's address: how@isl.stanford.edu + +$Id: README,v 1.15 1992/05/20 00:25:32 how E $ + + +==>> To compile after untarring/unsharring, just `make' <<== + + +This package was designed with the following goals: +1. Highest possible encryption/decryption PERFORMANCE. +2. PORTABILITY to any byte-addressable host with a 32bit unsigned C type +3. Plug-compatible replacement for KERBEROS's low-level routines. + +This second release includes a number of performance enhancements for +register-starved machines. My discussions with Richard Outerbridge, +71755.204@compuserve.com, sparked a number of these enhancements. + +To more rapidly understand the code in this package, inspect desSmallFips.i +(created by typing `make') BEFORE you tackle desCode.h. The latter is set +up in a parameterized fashion so it can easily be modified by speed-daemon +hackers in pursuit of that last microsecond. You will find it more +illuminating to inspect one specific implementation, +and then move on to the common abstract skeleton with this one in mind. + + +performance comparison to other available des code which i could +compile on a SPARCStation 1 (cc -O4, gcc -O2): + +this code (byte-order independent): + 30us per encryption (options: 64k tables, no IP/FP) + 33us per encryption (options: 64k tables, FIPS standard bit ordering) + 45us per encryption (options: 2k tables, no IP/FP) + 48us per encryption (options: 2k tables, FIPS standard bit ordering) + 275us to set a new key (uses 1k of key tables) + this has the quickest encryption/decryption routines i've seen. + since i was interested in fast des filters rather than crypt(3) + and password cracking, i haven't really bothered yet to speed up + the key setting routine. also, i have no interest in re-implementing + all the other junk in the mit kerberos des library, so i've just + provided my routines with little stub interfaces so they can be + used as drop-in replacements with mit's code or any of the mit- + compatible packages below. (note that the first two timings above + are highly variable because of cache effects). + +kerberos des replacement from australia (version 1.95): + 53us per encryption (uses 2k of tables) + 96us to set a new key (uses 2.25k of key tables) + so despite the author's inclusion of some of the performance + improvements i had suggested to him, this package's + encryption/decryption is still slower on the sparc and 68000. + more specifically, 19-40% slower on the 68020 and 11-35% slower + on the sparc, depending on the compiler; + in full gory detail (ALT_ECB is a libdes variant): + compiler machine desCore libdes ALT_ECB slower by + gcc 2.1 -O2 Sun 3/110 304 uS 369.5uS 461.8uS 22% + cc -O1 Sun 3/110 336 uS 436.6uS 399.3uS 19% + cc -O2 Sun 3/110 360 uS 532.4uS 505.1uS 40% + cc -O4 Sun 3/110 365 uS 532.3uS 505.3uS 38% + gcc 2.1 -O2 Sun 4/50 48 uS 53.4uS 57.5uS 11% + cc -O2 Sun 4/50 48 uS 64.6uS 64.7uS 35% + cc -O4 Sun 4/50 48 uS 64.7uS 64.9uS 35% + (my time measurements are not as accurate as his). + the comments in my first release of desCore on version 1.92: + 68us per encryption (uses 2k of tables) + 96us to set a new key (uses 2.25k of key tables) + this is a very nice package which implements the most important + of the optimizations which i did in my encryption routines. + it's a bit weak on common low-level optimizations which is why + it's 39%-106% slower. because he was interested in fast crypt(3) and + password-cracking applications, he also used the same ideas to + speed up the key-setting routines with impressive results. + (at some point i may do the same in my package). he also implements + the rest of the mit des library. + (code from eay@psych.psy.uq.oz.au via comp.sources.misc) + +fast crypt(3) package from denmark: + the des routine here is buried inside a loop to do the + crypt function and i didn't feel like ripping it out and measuring + performance. his code takes 26 sparc instructions to compute one + des iteration; above, Quick (64k) takes 21 and Small (2k) takes 37. + he claims to use 280k of tables but the iteration calculation seems + to use only 128k. his tables and code are machine independent. + (code from glad@daimi.aau.dk via alt.sources or comp.sources.misc) + +swedish reimplementation of Kerberos des library + 108us per encryption (uses 34k worth of tables) + 134us to set a new key (uses 32k of key tables to get this speed!) + the tables used seem to be machine-independent; + he seems to have included a lot of special case code + so that, e.g., `long' loads can be used instead of 4 `char' loads + when the machine's architecture allows it. + (code obtained from chalmers.se:pub/des) + +crack 3.3c package from england: + as in crypt above, the des routine is buried in a loop. it's + also very modified for crypt. his iteration code uses 16k + of tables and appears to be slow. + (code obtained from aem@aber.ac.uk via alt.sources or comp.sources.misc) + +``highly optimized'' and tweaked Kerberos/Athena code (byte-order dependent): + 165us per encryption (uses 6k worth of tables) + 478us to set a new key (uses <1k of key tables) + so despite the comments in this code, it was possible to get + faster code AND smaller tables, as well as making the tables + machine-independent. + (code obtained from prep.ai.mit.edu) + +UC Berkeley code (depends on machine-endedness): + 226us per encryption +10848us to set a new key + table sizes are unclear, but they don't look very small + (code obtained from wuarchive.wustl.edu) + + +motivation and history + +a while ago i wanted some des routines and the routines documented on sun's +man pages either didn't exist or dumped core. i had heard of kerberos, +and knew that it used des, so i figured i'd use its routines. but once +i got it and looked at the code, it really set off a lot of pet peeves - +it was too convoluted, the code had been written without taking +advantage of the regular structure of operations such as IP, E, and FP +(i.e. the author didn't sit down and think before coding), +it was excessively slow, the author had attempted to clarify the code +by adding MORE statements to make the data movement more `consistent' +instead of simplifying his implementation and cutting down on all data +movement (in particular, his use of L1, R1, L2, R2), and it was full of +idiotic `tweaks' for particular machines which failed to deliver significant +speedups but which did obfuscate everything. so i took the test data +from his verification program and rewrote everything else. + +a while later i ran across the great crypt(3) package mentioned above. +the fact that this guy was computing 2 sboxes per table lookup rather +than one (and using a MUCH larger table in the process) emboldened me to +do the same - it was a trivial change from which i had been scared away +by the larger table size. in his case he didn't realize you don't need to keep +the working data in TWO forms, one for easy use of half the sboxes in +indexing, the other for easy use of the other half; instead you can keep +it in the form for the first half and use a simple rotate to get the other +half. this means i have (almost) half the data manipulation and half +the table size. in fairness though he might be encoding something particular +to crypt(3) in his tables - i didn't check. + +i'm glad that i implemented it the way i did, because this C version is +portable (the ifdef's are performance enhancements) and it is faster +than versions hand-written in assembly for the sparc! + + +porting notes + +one thing i did not want to do was write an enormous mess +which depended on endedness and other machine quirks, +and which necessarily produced different code and different lookup tables +for different machines. see the kerberos code for an example +of what i didn't want to do; all their endedness-specific `optimizations' +obfuscate the code and in the end were slower than a simpler machine +independent approach. however, there are always some portability +considerations of some kind, and i have included some options +for varying numbers of register variables. +perhaps some will still regard the result as a mess! + +1) i assume everything is byte addressable, although i don't actually + depend on the byte order, and that bytes are 8 bits. + i assume word pointers can be freely cast to and from char pointers. + note that 99% of C programs make these assumptions. + i always use unsigned char's if the high bit could be set. +2) the typedef `word' means a 32 bit unsigned integral type. + if `unsigned long' is not 32 bits, change the typedef in desCore.h. + i assume sizeof(word) == 4 EVERYWHERE. + +the (worst-case) cost of my NOT doing endedness-specific optimizations +in the data loading and storing code surrounding the key iterations +is less than 12%. also, there is the added benefit that +the input and output work areas do not need to be word-aligned. + + +OPTIONAL performance optimizations + +1) you should define one of `i386,' `vax,' `mc68000,' or `sparc,' + whichever one is closest to the capabilities of your machine. + see the start of desCode.h to see exactly what this selection implies. + note that if you select the wrong one, the des code will still work; + these are just performance tweaks. +2) for those with functional `asm' keywords: you should change the + ROR and ROL macros to use machine rotate instructions if you have them. + this will save 2 instructions and a temporary per use, + or about 32 to 40 instructions per en/decryption. + note that gcc is smart enough to translate the ROL/R macros into + machine rotates! + +these optimizations are all rather persnickety, yet with them you should +be able to get performance equal to assembly-coding, except that: +1) with the lack of a bit rotate operator in C, rotates have to be synthesized + from shifts. so access to `asm' will speed things up if your machine + has rotates, as explained above in (3) (not necessary if you use gcc). +2) if your machine has less than 12 32-bit registers i doubt your compiler will + generate good code. + `i386' tries to configure the code for a 386 by only declaring 3 registers + (it appears that gcc can use ebx, esi and edi to hold register variables). + however, if you like assembly coding, the 386 does have 7 32-bit registers, + and if you use ALL of them, use `scaled by 8' address modes with displacement + and other tricks, you can get reasonable routines for DesQuickCore... with + about 250 instructions apiece. For DesSmall... it will help to rearrange + des_keymap, i.e., now the sbox # is the high part of the index and + the 6 bits of data is the low part; it helps to exchange these. + since i have no way to conveniently test it i have not provided my + shoehorned 386 version. note that with this release of desCore, gcc is able + to put everything in registers(!), and generate about 370 instructions apiece + for the DesQuickCore... routines! + +coding notes + +the en/decryption routines each use 6 necessary register variables, +with 4 being actively used at once during the inner iterations. +if you don't have 4 register variables get a new machine. +up to 8 more registers are used to hold constants in some configurations. + +i assume that the use of a constant is more expensive than using a register: +a) additionally, i have tried to put the larger constants in registers. + registering priority was by the following: + anything more than 12 bits (bad for RISC and CISC) + greater than 127 in value (can't use movq or byte immediate on CISC) + 9-127 (may not be able to use CISC shift immediate or add/sub quick), + 1-8 were never registered, being the cheapest constants. +b) the compiler may be too stupid to realize table and table+256 should + be assigned to different constant registers and instead repetitively + do the arithmetic, so i assign these to explicit `m' register variables + when possible and helpful. + +i assume that indexing is cheaper or equivalent to auto increment/decrement, +where the index is 7 bits unsigned or smaller. +this assumption is reversed for 68k and vax. + +i assume that addresses can be cheaply formed from two registers, +or from a register and a small constant. +for the 68000, the `two registers and small offset' form is used sparingly. +all index scaling is done explicitly - no hidden shifts by log2(sizeof). + +the code is written so that even a dumb compiler +should never need more than one hidden temporary, +increasing the chance that everything will fit in the registers. +KEEP THIS MORE SUBTLE POINT IN MIND IF YOU REWRITE ANYTHING. +(actually, there are some code fragments now which do require two temps, +but fixing it would either break the structure of the macros or +require declaring another temporary). + + +special efficient data format + +bits are manipulated in this arrangement most of the time (S7 S5 S3 S1): + 003130292827xxxx242322212019xxxx161514131211xxxx080706050403xxxx +(the x bits are still there, i'm just emphasizing where the S boxes are). +bits are rotated left 4 when computing S6 S4 S2 S0: + 282726252423xxxx201918171615xxxx121110090807xxxx040302010031xxxx +the rightmost two bits are usually cleared so the lower byte can be used +as an index into an sbox mapping table. the next two x'd bits are set +to various values to access different parts of the tables. + + +how to use the routines + +datatypes: + pointer to 8 byte area of type DesData + used to hold keys and input/output blocks to des. + + pointer to 128 byte area of type DesKeys + used to hold full 768-bit key. + must be long-aligned. + +DesQuickInit() + call this before using any other routine with `Quick' in its name. + it generates the special 64k table these routines need. +DesQuickDone() + frees this table + +DesMethod(m, k) + m points to a 128byte block, k points to an 8 byte des key + which must have odd parity (or -1 is returned) and which must + not be a (semi-)weak key (or -2 is returned). + normally DesMethod() returns 0. + m is filled in from k so that when one of the routines below + is called with m, the routine will act like standard des + en/decryption with the key k. if you use DesMethod, + you supply a standard 56bit key; however, if you fill in + m yourself, you will get a 768bit key - but then it won't + be standard. it's 768bits not 1024 because the least significant + two bits of each byte are not used. note that these two bits + will be set to magic constants which speed up the encryption/decryption + on some machines. and yes, each byte controls + a specific sbox during a specific iteration. + you really shouldn't use the 768bit format directly; i should + provide a routine that converts 128 6-bit bytes (specified in + S-box mapping order or something) into the right format for you. + this would entail some byte concatenation and rotation. + +Des{Small|Quick}{Fips|Core}{Encrypt|Decrypt}(d, m, s) + performs des on the 8 bytes at s into the 8 bytes at d. (d,s: char *). + uses m as a 768bit key as explained above. + the Encrypt|Decrypt choice is obvious. + Fips|Core determines whether a completely standard FIPS initial + and final permutation is done; if not, then the data is loaded + and stored in a nonstandard bit order (FIPS w/o IP/FP). + Fips slows down Quick by 10%, Small by 9%. + Small|Quick determines whether you use the normal routine + or the crazy quick one which gobbles up 64k more of memory. + Small is 50% slower then Quick, but Quick needs 32 times as much + memory. Quick is included for programs that do nothing but DES, + e.g., encryption filters, etc. + + +Getting it to compile on your machine + +there are no machine-dependencies in the code (see porting), +except perhaps the `now()' macro in desTest.c. +ALL generated tables are machine independent. +you should edit the Makefile with the appropriate optimization flags +for your compiler (MAX optimization). + + +Speeding up kerberos (and/or its des library) + +note that i have included a kerberos-compatible interface in desUtil.c +through the functions des_key_sched() and des_ecb_encrypt(). +to use these with kerberos or kerberos-compatible code put desCore.a +ahead of the kerberos-compatible library on your linker's command line. +you should not need to #include desCore.h; just include the header +file provided with the kerberos library. + +Other uses + +the macros in desCode.h would be very useful for putting inline des +functions in more complicated encryption routines. diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Wed Apr 23 17:09:06 2003 +++ b/MAINTAINERS Wed Apr 23 17:09:06 2003 @@ -430,6 +430,15 @@ W: http://developer.axis.com S: Maintained +CRYPTO API +P: James Morris +M: jmorris@intercode.com.au +P: David S. Miller +M: davem@redhat.com +W http://samba.org/~jamesm/crypto/ +L: linux-kernel@vger.kernel.org +S: Maintained + CYBERPRO FB DRIVER P: Russell King M: rmk@arm.linux.org.uk diff -Nru a/Makefile b/Makefile --- a/Makefile Wed Apr 23 17:09:05 2003 +++ b/Makefile Wed Apr 23 17:09:05 2003 @@ -125,7 +125,7 @@ NETWORKS =net/network.o LIBS =$(TOPDIR)/lib/lib.a -SUBDIRS =kernel drivers mm fs net ipc lib +SUBDIRS =kernel drivers mm fs net ipc lib crypto DRIVERS-n := DRIVERS-y := @@ -190,6 +190,7 @@ DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o +DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o DRIVERS := $(DRIVERS-y) diff -Nru a/arch/alpha/config.in b/arch/alpha/config.in --- a/arch/alpha/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/alpha/config.in Wed Apr 23 17:09:06 2003 @@ -443,4 +443,5 @@ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/arm/config.in b/arch/arm/config.in --- a/arch/arm/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/arm/config.in Wed Apr 23 17:09:06 2003 @@ -656,4 +656,5 @@ dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/cris/config.in b/arch/cris/config.in --- a/arch/cris/config.in Wed Apr 23 17:09:05 2003 +++ b/arch/cris/config.in Wed Apr 23 17:09:05 2003 @@ -261,5 +261,6 @@ int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +source crypto/Config.in source lib/Config.in endmenu diff -Nru a/arch/i386/config.in b/arch/i386/config.in --- a/arch/i386/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/i386/config.in Wed Apr 23 17:09:06 2003 @@ -484,4 +484,5 @@ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in --- a/arch/ia64/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/ia64/config.in Wed Apr 23 17:09:06 2003 @@ -243,6 +243,7 @@ source drivers/usb/Config.in source lib/Config.in + source crypto/Config.in if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then source net/bluetooth/Config.in diff -Nru a/arch/m68k/config.in b/arch/m68k/config.in --- a/arch/m68k/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/m68k/config.in Wed Apr 23 17:09:06 2003 @@ -559,4 +559,5 @@ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/mips/config-shared.in b/arch/mips/config-shared.in --- a/arch/mips/config-shared.in Wed Apr 23 17:09:06 2003 +++ b/arch/mips/config-shared.in Wed Apr 23 17:09:06 2003 @@ -800,4 +800,5 @@ fi endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/parisc/config.in b/arch/parisc/config.in --- a/arch/parisc/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/parisc/config.in Wed Apr 23 17:09:06 2003 @@ -196,4 +196,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in --- a/arch/ppc/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/ppc/config.in Wed Apr 23 17:09:06 2003 @@ -414,6 +414,7 @@ source net/bluetooth/Config.in +source crypto/Config.in source lib/Config.in mainmenu_option next_comment diff -Nru a/arch/ppc64/config.in b/arch/ppc64/config.in --- a/arch/ppc64/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/ppc64/config.in Wed Apr 23 17:09:06 2003 @@ -231,6 +231,8 @@ source lib/Config.in +source crypto/Config.in + mainmenu_option next_comment comment 'Kernel hacking' diff -Nru a/arch/s390/config.in b/arch/s390/config.in --- a/arch/s390/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/s390/config.in Wed Apr 23 17:09:06 2003 @@ -75,4 +75,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/s390x/config.in b/arch/s390x/config.in --- a/arch/s390x/config.in Wed Apr 23 17:09:05 2003 +++ b/arch/s390x/config.in Wed Apr 23 17:09:05 2003 @@ -79,4 +79,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/sh/config.in b/arch/sh/config.in --- a/arch/sh/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/sh/config.in Wed Apr 23 17:09:06 2003 @@ -387,4 +387,5 @@ fi endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/sparc/config.in b/arch/sparc/config.in --- a/arch/sparc/config.in Wed Apr 23 17:09:05 2003 +++ b/arch/sparc/config.in Wed Apr 23 17:09:05 2003 @@ -275,4 +275,5 @@ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/sparc64/config.in b/arch/sparc64/config.in --- a/arch/sparc64/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/sparc64/config.in Wed Apr 23 17:09:06 2003 @@ -309,4 +309,5 @@ endmenu +source crypto/Config.in source lib/Config.in diff -Nru a/arch/x86_64/config.in b/arch/x86_64/config.in --- a/arch/x86_64/config.in Wed Apr 23 17:09:06 2003 +++ b/arch/x86_64/config.in Wed Apr 23 17:09:06 2003 @@ -232,6 +232,8 @@ source net/bluetooth/Config.in +source crypto/Config.in + mainmenu_option next_comment comment 'Kernel hacking' diff -Nru a/crypto/Config.in b/crypto/Config.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/Config.in Wed Apr 23 17:09:06 2003 @@ -0,0 +1,61 @@ +# +# Cryptographic API Configuration +# +mainmenu_option next_comment +comment 'Cryptographic options' + +if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO y +else + bool 'Cryptographic API' CONFIG_CRYPTO +fi + +if [ "$CONFIG_CRYPTO" = "y" ]; then + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_HMAC y + else + bool ' HMAC support' CONFIG_CRYPTO_HMAC + fi + tristate ' NULL algorithms' CONFIG_CRYPTO_NULL + tristate ' MD4 digest algorithm' CONFIG_CRYPTO_MD4 + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_MD5 y + else + tristate ' MD5 digest algorithm' CONFIG_CRYPTO_MD5 + fi + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_SHA1 y + else + tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1 + fi + tristate ' SHA256 digest algorithm' CONFIG_CRYPTO_SHA256 + tristate ' SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512 + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_DES y + else + tristate ' DES and Triple DES EDE cipher algorithms' CONFIG_CRYPTO_DES + fi + tristate ' Blowfish cipher algorithm' CONFIG_CRYPTO_BLOWFISH + tristate ' Twofish cipher algorithm' CONFIG_CRYPTO_TWOFISH + tristate ' Serpent cipher algorithm' CONFIG_CRYPTO_SERPENT + tristate ' AES cipher algorithms' CONFIG_CRYPTO_AES + tristate ' Deflate compression algorithm' CONFIG_CRYPTO_DEFLATE + tristate ' Testing module' CONFIG_CRYPTO_TEST +fi + +endmenu diff -Nru a/crypto/Makefile b/crypto/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/Makefile Wed Apr 23 17:09:06 2003 @@ -0,0 +1,31 @@ +# +# Cryptographic API +# + +O_TARGET := crypto.o + +export-objs := api.o hmac.o + +autoload-crypto-$(CONFIG_KMOD) = autoload.o +proc-crypto-$(CONFIG_PROC_FS) = proc.o + +obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ + $(autoload-crypto-y) $(proc-crypto-y) + +obj-$(CONFIG_CRYPTO_HMAC) += hmac.o +obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o +obj-$(CONFIG_CRYPTO_MD4) += md4.o +obj-$(CONFIG_CRYPTO_MD5) += md5.o +obj-$(CONFIG_CRYPTO_SHA1) += sha1.o +obj-$(CONFIG_CRYPTO_SHA256) += sha256.o +obj-$(CONFIG_CRYPTO_SHA512) += sha512.o +obj-$(CONFIG_CRYPTO_DES) += des.o +obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o +obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o +obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o +obj-$(CONFIG_CRYPTO_AES) += aes.o +obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o + +obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o + +include $(TOPDIR)/Rules.make diff -Nru a/crypto/aes.c b/crypto/aes.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/aes.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,469 @@ +/* + * Cryptographic API. + * + * AES Cipher Algorithm. + * + * Based on Brian Gladman's code. + * + * Linux developers: + * Alexander Kjeldaas + * Herbert Valerio Riedel + * Kyle McMartin + * Adam J. Richter (conversion to 2.5 API). + * + * 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 2 of the License, or + * (at your option) any later version. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +/* Some changes from the Gladman version: + s/RIJNDAEL(e_key)/E_KEY/g + s/RIJNDAEL(d_key)/D_KEY/g +*/ + +#include +#include +#include +#include +#include +#include + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +#define AES_BLOCK_SIZE 16 + +static inline +u32 generic_rotr32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x >> n) | (x << (32 - n)); +} + +static inline +u32 generic_rotl32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x << n) | (x >> (32 - n)); +} + +#define rotl generic_rotl32 +#define rotr generic_rotr32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +inline static u8 +byte(const u32 x, const unsigned n) +{ + return x >> (n << 3); +} + +#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) +#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) + +struct aes_ctx { + int key_length; + u32 E[60]; + u32 D[60]; +}; + +#define E_KEY ctx->E +#define D_KEY ctx->D + +static u8 pow_tab[256]; +static u8 log_tab[256]; +static u8 sbx_tab[256]; +static u8 isb_tab[256]; +static u32 rco_tab[10]; +static u32 ft_tab[4][256]; +static u32 it_tab[4][256]; + +static u32 fl_tab[4][256]; +static u32 il_tab[4][256]; + +static inline u8 +f_mult (u8 a, u8 b) +{ + u8 aa = log_tab[a], cc = aa + log_tab[b]; + + return pow_tab[cc + (cc < aa ? 1 : 0)]; +} + +#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +static void +gen_tabs (void) +{ + u32 i, t; + u8 p, q; + + /* log and power tables for GF(2**8) finite field with + 0x011b as modular polynomial - the simplest prmitive + root is 0x03, used here to generate the tables */ + + for (i = 0, p = 1; i < 256; ++i) { + pow_tab[i] = (u8) p; + log_tab[p] = (u8) i; + + p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; + + for (i = 0, p = 1; i < 10; ++i) { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + for (i = 0; i < 256; ++i) { + p = (i ? pow_tab[255 - log_tab[i]] : 0); + q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2)); + p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2)); + sbx_tab[i] = p; + isb_tab[p] = (u8) i; + } + + for (i = 0; i < 256; ++i) { + p = sbx_tab[i]; + + t = p; + fl_tab[0][i] = t; + fl_tab[1][i] = rotl (t, 8); + fl_tab[2][i] = rotl (t, 16); + fl_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (2, p)) | + ((u32) p << 8) | + ((u32) p << 16) | ((u32) ff_mult (3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl (t, 8); + ft_tab[2][i] = rotl (t, 16); + ft_tab[3][i] = rotl (t, 24); + + p = isb_tab[i]; + + t = p; + il_tab[0][i] = t; + il_tab[1][i] = rotl (t, 8); + il_tab[2][i] = rotl (t, 16); + il_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (14, p)) | + ((u32) ff_mult (9, p) << 8) | + ((u32) ff_mult (13, p) << 16) | + ((u32) ff_mult (11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl (t, 8); + it_tab[2][i] = rotl (t, 16); + it_tab[3][i] = rotl (t, 24); + } +} + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \ + t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \ + t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \ + t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \ + t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \ + t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \ + t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \ + t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \ + t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \ + t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \ + t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \ + t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \ + t = E_KEY[8 * i + 4] ^ ls_box(t); \ + E_KEY[8 * i + 12] = t; \ + t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \ + t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \ + t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ +} + +static int +aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct aes_ctx *ctx = ctx_arg; + u32 i, t, u, v, w; + + if (key_len != 16 && key_len != 24 && key_len != 32) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + ctx->key_length = key_len; + + E_KEY[0] = u32_in (in_key); + E_KEY[1] = u32_in (in_key + 4); + E_KEY[2] = u32_in (in_key + 8); + E_KEY[3] = u32_in (in_key + 12); + + switch (key_len) { + case 16: + t = E_KEY[3]; + for (i = 0; i < 10; ++i) + loop4 (i); + break; + + case 24: + E_KEY[4] = u32_in (in_key + 16); + t = E_KEY[5] = u32_in (in_key + 20); + for (i = 0; i < 8; ++i) + loop6 (i); + break; + + case 32: + E_KEY[4] = u32_in (in_key + 16); + E_KEY[5] = u32_in (in_key + 20); + E_KEY[6] = u32_in (in_key + 24); + t = E_KEY[7] = u32_in (in_key + 28); + for (i = 0; i < 7; ++i) + loop8 (i); + break; + } + + D_KEY[0] = E_KEY[0]; + D_KEY[1] = E_KEY[1]; + D_KEY[2] = E_KEY[2]; + D_KEY[3] = E_KEY[3]; + + for (i = 4; i < key_len + 24; ++i) { + imix_col (D_KEY[i], E_KEY[i]); + } + + return 0; +} + +/* encrypt a block of text */ + +#define f_nround(bo, bi, k) \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4 + +#define f_lround(bo, bi, k) \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k) + +static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const u32 *kp = E_KEY + 4; + + b0[0] = u32_in (in) ^ E_KEY[0]; + b0[1] = u32_in (in + 4) ^ E_KEY[1]; + b0[2] = u32_in (in + 8) ^ E_KEY[2]; + b0[3] = u32_in (in + 12) ^ E_KEY[3]; + + if (ctx->key_length > 24) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + if (ctx->key_length > 16) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, k); \ + i_rl(bo, bi, 2, k); \ + i_rl(bo, bi, 3, k) + +static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const int key_len = ctx->key_length; + const u32 *kp = D_KEY + key_len + 20; + + b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; + b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; + b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; + b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + + if (key_len > 24) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + if (key_len > 16) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_ivsize = AES_BLOCK_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); +MODULE_LICENSE("Dual BSD/GPL"); + diff -Nru a/crypto/api.c b/crypto/api.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/api.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,227 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Möller. + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +LIST_HEAD(crypto_alg_list); +DECLARE_RWSEM(crypto_alg_sem); + +static inline int crypto_alg_get(struct crypto_alg *alg) +{ + return try_inc_mod_count(alg->cra_module); +} + +static inline void crypto_alg_put(struct crypto_alg *alg) +{ + if (alg->cra_module) + __MOD_DEC_USE_COUNT(alg->cra_module); +} + +struct crypto_alg *crypto_alg_lookup(const char *name) +{ + struct crypto_alg *q, *alg = NULL; + + down_read(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, name))) { + if (crypto_alg_get(q)) + alg = q; + break; + } + } + + up_read(&crypto_alg_sem); + return alg; +} + +static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) +{ + tfm->crt_flags = 0; + + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_flags(tfm, flags); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static int crypto_init_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_ops(tfm); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_ops(tfm); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_ops(tfm); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static void crypto_exit_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + crypto_exit_cipher_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + crypto_exit_digest_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_COMPRESS: + crypto_exit_compress_ops(tfm); + break; + + default: + BUG(); + + } +} + +struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name); + if (alg == NULL) + goto out; + + tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); + if (tfm == NULL) + goto out_put; + + memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); + + tfm->__crt_alg = alg; + + if (crypto_init_flags(tfm, flags)) + goto out_free_tfm; + + if (crypto_init_ops(tfm)) { + crypto_exit_ops(tfm); + goto out_free_tfm; + } + + goto out; + +out_free_tfm: + kfree(tfm); + tfm = NULL; +out_put: + crypto_alg_put(alg); +out: + return tfm; +} + +void crypto_free_tfm(struct crypto_tfm *tfm) +{ + crypto_exit_ops(tfm); + crypto_alg_put(tfm->__crt_alg); + kfree(tfm); +} + +int crypto_register_alg(struct crypto_alg *alg) +{ + int ret = 0; + struct crypto_alg *q; + + down_write(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, alg->cra_name))) { + ret = -EEXIST; + goto out; + } + } + + list_add_tail(&alg->cra_list, &crypto_alg_list); +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_unregister_alg(struct crypto_alg *alg) +{ + int ret = -ENOENT; + struct crypto_alg *q; + + BUG_ON(!alg->cra_module); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (alg == q) { + list_del(&alg->cra_list); + ret = 0; + goto out; + } + } +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_alg_available(const char *name, u32 flags) +{ + int ret = 0; + struct crypto_alg *alg = crypto_alg_mod_lookup(name); + + if (alg) { + crypto_alg_put(alg); + ret = 1; + } + + return ret; +} + +static int __init init_crypto(void) +{ + printk(KERN_INFO "Initializing Cryptographic API\n"); + crypto_init_proc(); + return 0; +} + +__initcall(init_crypto); + +EXPORT_SYMBOL_GPL(crypto_register_alg); +EXPORT_SYMBOL_GPL(crypto_unregister_alg); +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_alg_available); diff -Nru a/crypto/autoload.c b/crypto/autoload.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/autoload.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,37 @@ +/* + * Cryptographic API. + * + * Algorithm autoloader. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include "internal.h" + +/* + * A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. + */ +void crypto_alg_autoload(const char *name) +{ + request_module(name); +} + +struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + struct crypto_alg *alg = crypto_alg_lookup(name); + if (alg == NULL) { + crypto_alg_autoload(name); + alg = crypto_alg_lookup(name); + } + return alg; +} diff -Nru a/crypto/blowfish.c b/crypto/blowfish.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/blowfish.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,479 @@ +/* + * Cryptographic API. + * + * Blowfish Cipher Algorithm, by Bruce Schneier. + * http://www.counterpane.com/blowfish.html + * + * Adapated from Kerneli implementation. + * + * Copyright (c) Herbert Valerio Riedel + * Copyright (c) Kyle McMartin + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define BF_BLOCK_SIZE 8 +#define BF_MIN_KEY_SIZE 4 +#define BF_MAX_KEY_SIZE 56 + +struct bf_ctx { + u32 p[18]; + u32 s[1024]; +}; + +static const u32 bf_pbox[16 + 2] = { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static const u32 bf_sbox[256 * 4] = { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, +}; + +/* + * Round loop unrolling macros, S is a pointer to a S-Box array + * organized in 4 unsigned longs at a row. + */ +#define GET32_3(x) (((x) & 0xff)) +#define GET32_2(x) (((x) >> (8)) & (0xff)) +#define GET32_1(x) (((x) >> (16)) & (0xff)) +#define GET32_0(x) (((x) >> (24)) & (0xff)) + +#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ + S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) + +#define ROUND(a, b, n) b ^= P[n]; a ^= bf_F (b) + +/* + * The blowfish encipher, processes 64-bit blocks. + * NOTE: This function MUSTN'T respect endianess + */ +static inline void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src) +{ + const u32 *P = bctx->p; + const u32 *S = bctx->s; + u32 yl = src[0]; + u32 yr = src[1]; + + ROUND(yr, yl, 0); + ROUND(yl, yr, 1); + ROUND(yr, yl, 2); + ROUND(yl, yr, 3); + ROUND(yr, yl, 4); + ROUND(yl, yr, 5); + ROUND(yr, yl, 6); + ROUND(yl, yr, 7); + ROUND(yr, yl, 8); + ROUND(yl, yr, 9); + ROUND(yr, yl, 10); + ROUND(yl, yr, 11); + ROUND(yr, yl, 12); + ROUND(yl, yr, 13); + ROUND(yr, yl, 14); + ROUND(yl, yr, 15); + + yl ^= P[16]; + yr ^= P[17]; + + dst[0] = yr; + dst[1] = yl; +} + +static void bf_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 *in_blk = (const u32 *)src; + u32 *const out_blk = (u32 *)dst; + u32 in32[2], out32[2]; + + in32[0] = be32_to_cpu(in_blk[0]); + in32[1] = be32_to_cpu(in_blk[1]); + encrypt_block(ctx, out32, in32); + out_blk[0] = cpu_to_be32(out32[0]); + out_blk[1] = cpu_to_be32(out32[1]); +} + +static void bf_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 *in_blk = (const u32 *)src; + u32 *const out_blk = (u32 *)dst; + const u32 *P = ((struct bf_ctx *)ctx)->p; + const u32 *S = ((struct bf_ctx *)ctx)->s; + u32 yl = be32_to_cpu(in_blk[0]); + u32 yr = be32_to_cpu(in_blk[1]); + + ROUND(yr, yl, 17); + ROUND(yl, yr, 16); + ROUND(yr, yl, 15); + ROUND(yl, yr, 14); + ROUND(yr, yl, 13); + ROUND(yl, yr, 12); + ROUND(yr, yl, 11); + ROUND(yl, yr, 10); + ROUND(yr, yl, 9); + ROUND(yl, yr, 8); + ROUND(yr, yl, 7); + ROUND(yl, yr, 6); + ROUND(yr, yl, 5); + ROUND(yl, yr, 4); + ROUND(yr, yl, 3); + ROUND(yl, yr, 2); + + yl ^= P[1]; + yr ^= P[0]; + + out_blk[0] = cpu_to_be32(yr); + out_blk[1] = cpu_to_be32(yl); +} + +/* + * Calculates the blowfish S and P boxes for encryption and decryption. + */ +static int bf_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + short i, j, count; + u32 data[2], temp; + u32 *P = ((struct bf_ctx *)ctx)->p; + u32 *S = ((struct bf_ctx *)ctx)->s; + + /* Copy the initialization s-boxes */ + for (i = 0, count = 0; i < 256; i++) + for (j = 0; j < 4; j++, count++) + S[count] = bf_sbox[count]; + + /* Set the p-boxes */ + for (i = 0; i < 16 + 2; i++) + P[i] = bf_pbox[i]; + + /* Actual subkey generation */ + for (j = 0, i = 0; i < 16 + 2; i++) { + temp = (((u32 )key[j] << 24) | + ((u32 )key[(j + 1) % keylen] << 16) | + ((u32 )key[(j + 2) % keylen] << 8) | + ((u32 )key[(j + 3) % keylen])); + + P[i] = P[i] ^ temp; + j = (j + 4) % keylen; + } + + data[0] = 0x00000000; + data[1] = 0x00000000; + + for (i = 0; i < 16 + 2; i += 2) { + encrypt_block((struct bf_ctx *)ctx, data, data); + + P[i] = data[0]; + P[i + 1] = data[1]; + } + + for (i = 0; i < 4; i++) { + for (j = 0, count = i * 256; j < 256; j += 2, count += 2) { + encrypt_block((struct bf_ctx *)ctx, data, data); + + S[count] = data[0]; + S[count + 1] = data[1]; + } + } + + /* Bruce says not to bother with the weak key check. */ + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "blowfish", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = BF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct bf_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = BF_MIN_KEY_SIZE, + .cia_max_keysize = BF_MAX_KEY_SIZE, + .cia_ivsize = BF_BLOCK_SIZE, + .cia_setkey = bf_setkey, + .cia_encrypt = bf_encrypt, + .cia_decrypt = bf_decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Blowfish Cipher Algorithm"); diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/cipher.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,417 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * Generic scatterwalk code by Adam J. Richter . + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +typedef void (cryptfn_t)(void *, u8 *, const u8 *); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +static inline void xor_64(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; +} + +static inline void xor_128(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; + ((u32 *)a)[2] ^= ((u32 *)b)[2]; + ((u32 *)a)[3] ^= ((u32 *)b)[3]; +} + + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +static void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatter_page_done(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virutual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +static void scatter_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatter_page_done(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +static int copy_chunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatter_page_done(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} + +/* + * Generic encrypt/decrypt wrapper for ciphers, handles operations across + * multiple page boundaries by using temporary blocks. In user context, + * the kernel is given a chance to schedule us once per block. + */ +static int crypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) +{ + struct scatter_walk walk_in, walk_out; + const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); + u8 tmp_src[nbytes > src->length ? bsize : 0]; + u8 tmp_dst[nbytes > dst->length ? bsize : 0]; + + if (!nbytes) + return 0; + + if (nbytes % bsize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + scatterwalk_start(&walk_in, src); + scatterwalk_start(&walk_out, dst); + + for(;;) { + u8 *src_p, *dst_p; + + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + src_p = which_buf(&walk_in, bsize, tmp_src); + dst_p = which_buf(&walk_out, bsize, tmp_dst); + + nbytes -= bsize; + + copy_chunks(src_p, &walk_in, bsize, 0); + + prfn(tfm, dst_p, src_p, crfn, enc, info); + + scatter_done(&walk_in, 0, nbytes); + + copy_chunks(dst_p, &walk_out, bsize, 1); + scatter_done(&walk_out, 1, nbytes); + + if (!nbytes) + return 0; + + crypto_yield(tfm); + } +} + +static void cbc_process(struct crypto_tfm *tfm, + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) +{ + u8 *iv = info; + + /* Null encryption */ + if (!iv) + return; + + if (enc) { + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); + } else { + const int need_stack = (src == dst); + u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = need_stack ? stack : dst; + + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); + if (buf != dst) + memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); + } +} + +static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info) +{ + fn(crypto_tfm_ctx(tfm), dst, src); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; + + if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } else + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, + &tfm->crt_flags); +} + +static int ecb_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); +} + +static int ecb_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); +} + +static int cbc_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); +} + +static int cbc_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); +} + +static int nocrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return -ENOSYS; +} + +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) +{ + u32 mode = flags & CRYPTO_TFM_MODE_MASK; + + tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; + if (flags & CRYPTO_TFM_REQ_WEAK_KEY) + tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; + + return 0; +} + +int crypto_init_cipher_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct crypto_alg *alg = tfm->__crt_alg; + struct cipher_tfm *ops = &tfm->crt_cipher; + + ops->cit_setkey = setkey; + + switch (tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_ECB: + ops->cit_encrypt = ecb_encrypt; + ops->cit_decrypt = ecb_decrypt; + break; + + case CRYPTO_TFM_MODE_CBC: + ops->cit_encrypt = cbc_encrypt; + ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; + break; + + case CRYPTO_TFM_MODE_CFB: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + case CRYPTO_TFM_MODE_CTR: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + default: + BUG(); + } + + if (alg->cra_cipher.cia_ivsize && + ops->cit_mode != CRYPTO_TFM_MODE_ECB) { + + switch (crypto_tfm_alg_blocksize(tfm)) { + case 8: + ops->cit_xor_block = xor_64; + break; + + case 16: + ops->cit_xor_block = xor_128; + break; + + default: + printk(KERN_WARNING "%s: block size %u not supported\n", + crypto_tfm_alg_name(tfm), + crypto_tfm_alg_blocksize(tfm)); + ret = -EINVAL; + goto out; + } + + ops->cit_iv = kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL); + if (ops->cit_iv == NULL) + ret = -ENOMEM; + } + +out: + return ret; +} + +void crypto_exit_cipher_ops(struct crypto_tfm *tfm) +{ + if (tfm->crt_cipher.cit_iv) + kfree(tfm->crt_cipher.cit_iv); +} diff -Nru a/crypto/compress.c b/crypto/compress.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/compress.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,63 @@ +/* + * Cryptographic API. + * + * Compression operations. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static int crypto_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +static int crypto_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_compress_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct compress_tfm *ops = &tfm->crt_compress; + + ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm)); + if (ret) + goto out; + + ops->cot_compress = crypto_compress; + ops->cot_decompress = crypto_decompress; + +out: + return ret; +} + +void crypto_exit_compress_ops(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm)); +} diff -Nru a/crypto/crypto_null.c b/crypto/crypto_null.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/crypto_null.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,134 @@ +/* + * Cryptographic API. + * + * Null algorithms, aka Much Ado About Nothing. + * + * These are needed for IPsec, and may be useful in general for + * testing & debugging. + * + * The null cipher is compliant with RFC2410. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define NULL_KEY_SIZE 0 +#define NULL_BLOCK_SIZE 1 +#define NULL_DIGEST_SIZE 0 + +static int null_compress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ return 0; } + +static int null_decompress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ return 0; } + +static void null_init(void *ctx) +{ } + +static void null_update(void *ctx, const u8 *data, unsigned int len) +{ } + +static void null_final(void *ctx, u8 *out) +{ } + +static int null_setkey(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags) +{ return 0; } + +static void null_encrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static void null_decrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static struct crypto_alg compress_null = { + .cra_name = "compress_null", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(compress_null.cra_list), + .cra_u = { .compress = { + .coa_compress = null_compress, + .coa_decompress = null_decompress } } +}; + +static struct crypto_alg digest_null = { + .cra_name = "digest_null", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(digest_null.cra_list), + .cra_u = { .digest = { + .dia_digestsize = NULL_DIGEST_SIZE, + .dia_init = null_init, + .dia_update = null_update, + .dia_final = null_final } } +}; + +static struct crypto_alg cipher_null = { + .cra_name = "cipher_null", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(cipher_null.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = NULL_KEY_SIZE, + .cia_max_keysize = NULL_KEY_SIZE, + .cia_ivsize = 0, + .cia_setkey = null_setkey, + .cia_encrypt = null_encrypt, + .cia_decrypt = null_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&cipher_null); + if (ret < 0) + goto out; + + ret = crypto_register_alg(&digest_null); + if (ret < 0) { + crypto_unregister_alg(&cipher_null); + goto out; + } + + ret = crypto_register_alg(&compress_null); + if (ret < 0) { + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); + goto out; + } + +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&compress_null); + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Null Cryptographic Algorithms"); diff -Nru a/crypto/deflate.c b/crypto/deflate.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/deflate.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,236 @@ +/* + * Cryptographic API. + * + * Deflate algorithm (RFC 1951), implemented here primarily for use + * by IPCOMP (RFC 3173 & RFC 2394). + * + * Copyright (c) 2003 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + * FIXME: deflate transforms will require up to a total of about 436k of kernel + * memory on i386 (390k for compression, the rest for decompression), as the + * current zlib kernel code uses a worst case pre-allocation system by default. + * This needs to be fixed so that the amount of memory required is properly + * related to the winbits and memlevel parameters. + * + * The default winbits of 11 should suit most packets, and it may be something + * to configure on a per-tfm basis in the future. + * + * Currently, compression history is not maintained between tfm calls, as + * it is not needed for IPCOMP and keeps the code simpler. It can be + * implemented if someone wants it. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION +#define DEFLATE_DEF_WINBITS 11 +#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL + +struct deflate_ctx { + int comp_initialized; + int decomp_initialized; + struct z_stream_s comp_stream; + struct z_stream_s decomp_stream; +}; + +static inline int deflate_gfp(void) +{ + return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; +} + +static int deflate_init(void *ctx) +{ + return 0; +} + +static void deflate_exit(void *ctx) +{ + struct deflate_ctx *dctx = ctx; + + if (dctx->comp_initialized) + vfree(dctx->comp_stream.workspace); + if (dctx->decomp_initialized) + kfree(dctx->decomp_stream.workspace); +} + +/* + * Lazy initialization to make interface simple without allocating + * un-needed workspaces. Thus can be called in softirq context. + */ +static int deflate_comp_init(struct deflate_ctx *ctx) +{ + int ret = 0; + struct z_stream_s *stream = &ctx->comp_stream; + + stream->workspace = __vmalloc(zlib_deflate_workspacesize(), + deflate_gfp()|__GFP_HIGHMEM, + PAGE_KERNEL); + if (!stream->workspace ) { + ret = -ENOMEM; + goto out; + } + memset(stream->workspace, 0, sizeof(stream->workspace)); + ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, + -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + ret = -EINVAL; + goto out_free; + } + ctx->comp_initialized = 1; +out: + return ret; +out_free: + vfree(stream->workspace); + goto out; +} + +static int deflate_decomp_init(struct deflate_ctx *ctx) +{ + int ret = 0; + struct z_stream_s *stream = &ctx->decomp_stream; + + stream->workspace = kmalloc(zlib_inflate_workspacesize(), + deflate_gfp()); + if (!stream->workspace ) { + ret = -ENOMEM; + goto out; + } + memset(stream->workspace, 0, sizeof(stream->workspace)); + ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS); + if (ret != Z_OK) { + ret = -EINVAL; + goto out_free; + } + ctx->decomp_initialized = 1; +out: + return ret; +out_free: + kfree(stream->workspace); + goto out; +} + +static int deflate_compress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + int ret = 0; + struct deflate_ctx *dctx = ctx; + struct z_stream_s *stream = &dctx->comp_stream; + + if (!dctx->comp_initialized) { + ret = deflate_comp_init(dctx); + if (ret) + goto out; + } + + ret = zlib_deflateReset(stream); + if (ret != Z_OK) { + ret = -EINVAL; + goto out; + } + + stream->next_in = (u8 *)src; + stream->avail_in = slen; + stream->next_out = (u8 *)dst; + stream->avail_out = *dlen; + + ret = zlib_deflate(stream, Z_FINISH); + if (ret != Z_STREAM_END) { + ret = -EINVAL; + goto out; + } + ret = 0; + *dlen = stream->total_out; +out: + return ret; +} + +static int deflate_decompress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + + int ret = 0; + struct deflate_ctx *dctx = ctx; + struct z_stream_s *stream = &dctx->decomp_stream; + + if (!dctx->decomp_initialized) { + ret = deflate_decomp_init(dctx); + if (ret) + goto out; + } + + ret = zlib_inflateReset(stream); + if (ret != Z_OK) { + ret = -EINVAL; + goto out; + } + + stream->next_in = (u8 *)src; + stream->avail_in = slen; + stream->next_out = (u8 *)dst; + stream->avail_out = *dlen; + + ret = zlib_inflate(stream, Z_SYNC_FLUSH); + /* + * Work around a bug in zlib, which sometimes wants to taste an extra + * byte when being used in the (undocumented) raw deflate mode. + * (From USAGI). + */ + if (ret == Z_OK && !stream->avail_in && stream->avail_out) { + u8 zerostuff = 0; + stream->next_in = &zerostuff; + stream->avail_in = 1; + ret = zlib_inflate(stream, Z_FINISH); + } + if (ret != Z_STREAM_END) { + ret = -EINVAL; + goto out; + } + ret = 0; + *dlen = stream->total_out; +out: + return ret; +} + +static struct crypto_alg alg = { + .cra_name = "deflate", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct deflate_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .compress = { + .coa_init = deflate_init, + .coa_exit = deflate_exit, + .coa_compress = deflate_compress, + .coa_decompress = deflate_decompress } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP"); +MODULE_AUTHOR("James Morris "); + diff -Nru a/crypto/des.c b/crypto/des.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/des.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,1299 @@ +/* + * Cryptographic API. + * + * DES & Triple DES EDE Cipher Algorithms. + * + * Originally released as descore by Dana L. How . + * Modified by Raimar Falke for the Linux-Kernel. + * Derived from Cryptoapi and Nettle implementations, adapted for in-place + * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL. + * + * Copyright (c) 1992 Dana L. How. + * Copyright (c) Raimar Falke + * Copyright (c) Gisle Sælensminde + * Copyright (C) 2001 Niels Möller. + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define DES_KEY_SIZE 8 +#define DES_EXPKEY_WORDS 32 +#define DES_BLOCK_SIZE 8 + +#define DES3_EDE_KEY_SIZE (3 * DES_KEY_SIZE) +#define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS) +#define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE + +#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o)) + +struct des_ctx { + u8 iv[DES_BLOCK_SIZE]; + u32 expkey[DES_EXPKEY_WORDS]; +}; + +struct des3_ede_ctx { + u8 iv[DES_BLOCK_SIZE]; + u32 expkey[DES3_EDE_EXPKEY_WORDS]; +}; + +const static u32 des_keymap[] = { + 0x02080008, 0x02082000, 0x00002008, 0x00000000, + 0x02002000, 0x00080008, 0x02080000, 0x02082008, + 0x00000008, 0x02000000, 0x00082000, 0x00002008, + 0x00082008, 0x02002008, 0x02000008, 0x02080000, + 0x00002000, 0x00082008, 0x00080008, 0x02002000, + 0x02082008, 0x02000008, 0x00000000, 0x00082000, + 0x02000000, 0x00080000, 0x02002008, 0x02080008, + 0x00080000, 0x00002000, 0x02082000, 0x00000008, + 0x00080000, 0x00002000, 0x02000008, 0x02082008, + 0x00002008, 0x02000000, 0x00000000, 0x00082000, + 0x02080008, 0x02002008, 0x02002000, 0x00080008, + 0x02082000, 0x00000008, 0x00080008, 0x02002000, + 0x02082008, 0x00080000, 0x02080000, 0x02000008, + 0x00082000, 0x00002008, 0x02002008, 0x02080000, + 0x00000008, 0x02082000, 0x00082008, 0x00000000, + 0x02000000, 0x02080008, 0x00002000, 0x00082008, + + 0x08000004, 0x00020004, 0x00000000, 0x08020200, + 0x00020004, 0x00000200, 0x08000204, 0x00020000, + 0x00000204, 0x08020204, 0x00020200, 0x08000000, + 0x08000200, 0x08000004, 0x08020000, 0x00020204, + 0x00020000, 0x08000204, 0x08020004, 0x00000000, + 0x00000200, 0x00000004, 0x08020200, 0x08020004, + 0x08020204, 0x08020000, 0x08000000, 0x00000204, + 0x00000004, 0x00020200, 0x00020204, 0x08000200, + 0x00000204, 0x08000000, 0x08000200, 0x00020204, + 0x08020200, 0x00020004, 0x00000000, 0x08000200, + 0x08000000, 0x00000200, 0x08020004, 0x00020000, + 0x00020004, 0x08020204, 0x00020200, 0x00000004, + 0x08020204, 0x00020200, 0x00020000, 0x08000204, + 0x08000004, 0x08020000, 0x00020204, 0x00000000, + 0x00000200, 0x08000004, 0x08000204, 0x08020200, + 0x08020000, 0x00000204, 0x00000004, 0x08020004, + + 0x80040100, 0x01000100, 0x80000000, 0x81040100, + 0x00000000, 0x01040000, 0x81000100, 0x80040000, + 0x01040100, 0x81000000, 0x01000000, 0x80000100, + 0x81000000, 0x80040100, 0x00040000, 0x01000000, + 0x81040000, 0x00040100, 0x00000100, 0x80000000, + 0x00040100, 0x81000100, 0x01040000, 0x00000100, + 0x80000100, 0x00000000, 0x80040000, 0x01040100, + 0x01000100, 0x81040000, 0x81040100, 0x00040000, + 0x81040000, 0x80000100, 0x00040000, 0x81000000, + 0x00040100, 0x01000100, 0x80000000, 0x01040000, + 0x81000100, 0x00000000, 0x00000100, 0x80040000, + 0x00000000, 0x81040000, 0x01040100, 0x00000100, + 0x01000000, 0x81040100, 0x80040100, 0x00040000, + 0x81040100, 0x80000000, 0x01000100, 0x80040100, + 0x80040000, 0x00040100, 0x01040000, 0x81000100, + 0x80000100, 0x01000000, 0x81000000, 0x01040100, + + 0x04010801, 0x00000000, 0x00010800, 0x04010000, + 0x04000001, 0x00000801, 0x04000800, 0x00010800, + 0x00000800, 0x04010001, 0x00000001, 0x04000800, + 0x00010001, 0x04010800, 0x04010000, 0x00000001, + 0x00010000, 0x04000801, 0x04010001, 0x00000800, + 0x00010801, 0x04000000, 0x00000000, 0x00010001, + 0x04000801, 0x00010801, 0x04010800, 0x04000001, + 0x04000000, 0x00010000, 0x00000801, 0x04010801, + 0x00010001, 0x04010800, 0x04000800, 0x00010801, + 0x04010801, 0x00010001, 0x04000001, 0x00000000, + 0x04000000, 0x00000801, 0x00010000, 0x04010001, + 0x00000800, 0x04000000, 0x00010801, 0x04000801, + 0x04010800, 0x00000800, 0x00000000, 0x04000001, + 0x00000001, 0x04010801, 0x00010800, 0x04010000, + 0x04010001, 0x00010000, 0x00000801, 0x04000800, + 0x04000801, 0x00000001, 0x04010000, 0x00010800, + + 0x00000400, 0x00000020, 0x00100020, 0x40100000, + 0x40100420, 0x40000400, 0x00000420, 0x00000000, + 0x00100000, 0x40100020, 0x40000020, 0x00100400, + 0x40000000, 0x00100420, 0x00100400, 0x40000020, + 0x40100020, 0x00000400, 0x40000400, 0x40100420, + 0x00000000, 0x00100020, 0x40100000, 0x00000420, + 0x40100400, 0x40000420, 0x00100420, 0x40000000, + 0x40000420, 0x40100400, 0x00000020, 0x00100000, + 0x40000420, 0x00100400, 0x40100400, 0x40000020, + 0x00000400, 0x00000020, 0x00100000, 0x40100400, + 0x40100020, 0x40000420, 0x00000420, 0x00000000, + 0x00000020, 0x40100000, 0x40000000, 0x00100020, + 0x00000000, 0x40100020, 0x00100020, 0x00000420, + 0x40000020, 0x00000400, 0x40100420, 0x00100000, + 0x00100420, 0x40000000, 0x40000400, 0x40100420, + 0x40100000, 0x00100420, 0x00100400, 0x40000400, + + 0x00800000, 0x00001000, 0x00000040, 0x00801042, + 0x00801002, 0x00800040, 0x00001042, 0x00801000, + 0x00001000, 0x00000002, 0x00800002, 0x00001040, + 0x00800042, 0x00801002, 0x00801040, 0x00000000, + 0x00001040, 0x00800000, 0x00001002, 0x00000042, + 0x00800040, 0x00001042, 0x00000000, 0x00800002, + 0x00000002, 0x00800042, 0x00801042, 0x00001002, + 0x00801000, 0x00000040, 0x00000042, 0x00801040, + 0x00801040, 0x00800042, 0x00001002, 0x00801000, + 0x00001000, 0x00000002, 0x00800002, 0x00800040, + 0x00800000, 0x00001040, 0x00801042, 0x00000000, + 0x00001042, 0x00800000, 0x00000040, 0x00001002, + 0x00800042, 0x00000040, 0x00000000, 0x00801042, + 0x00801002, 0x00801040, 0x00000042, 0x00001000, + 0x00001040, 0x00801002, 0x00800040, 0x00000042, + 0x00000002, 0x00001042, 0x00801000, 0x00800002, + + 0x10400000, 0x00404010, 0x00000010, 0x10400010, + 0x10004000, 0x00400000, 0x10400010, 0x00004010, + 0x00400010, 0x00004000, 0x00404000, 0x10000000, + 0x10404010, 0x10000010, 0x10000000, 0x10404000, + 0x00000000, 0x10004000, 0x00404010, 0x00000010, + 0x10000010, 0x10404010, 0x00004000, 0x10400000, + 0x10404000, 0x00400010, 0x10004010, 0x00404000, + 0x00004010, 0x00000000, 0x00400000, 0x10004010, + 0x00404010, 0x00000010, 0x10000000, 0x00004000, + 0x10000010, 0x10004000, 0x00404000, 0x10400010, + 0x00000000, 0x00404010, 0x00004010, 0x10404000, + 0x10004000, 0x00400000, 0x10404010, 0x10000000, + 0x10004010, 0x10400000, 0x00400000, 0x10404010, + 0x00004000, 0x00400010, 0x10400010, 0x00004010, + 0x00400010, 0x00000000, 0x10404000, 0x10000010, + 0x10400000, 0x10004010, 0x00000010, 0x00404000, + + 0x00208080, 0x00008000, 0x20200000, 0x20208080, + 0x00200000, 0x20008080, 0x20008000, 0x20200000, + 0x20008080, 0x00208080, 0x00208000, 0x20000080, + 0x20200080, 0x00200000, 0x00000000, 0x20008000, + 0x00008000, 0x20000000, 0x00200080, 0x00008080, + 0x20208080, 0x00208000, 0x20000080, 0x00200080, + 0x20000000, 0x00000080, 0x00008080, 0x20208000, + 0x00000080, 0x20200080, 0x20208000, 0x00000000, + 0x00000000, 0x20208080, 0x00200080, 0x20008000, + 0x00208080, 0x00008000, 0x20000080, 0x00200080, + 0x20208000, 0x00000080, 0x00008080, 0x20200000, + 0x20008080, 0x20000000, 0x20200000, 0x00208000, + 0x20208080, 0x00008080, 0x00208000, 0x20200080, + 0x00200000, 0x20000080, 0x20008000, 0x00000000, + 0x00008000, 0x00200000, 0x20200080, 0x00208080, + 0x20000000, 0x20208000, 0x00000080, 0x20008080, +}; + +const static u8 rotors[] = { + 34, 13, 5, 46, 47, 18, 32, 41, 11, 53, 33, 20, + 14, 36, 30, 24, 49, 2, 15, 37, 42, 50, 0, 21, + 38, 48, 6, 26, 39, 4, 52, 25, 12, 27, 31, 40, + 1, 17, 28, 29, 23, 51, 35, 7, 3, 22, 9, 43, + + 41, 20, 12, 53, 54, 25, 39, 48, 18, 31, 40, 27, + 21, 43, 37, 0, 1, 9, 22, 44, 49, 2, 7, 28, + 45, 55, 13, 33, 46, 11, 6, 32, 19, 34, 38, 47, + 8, 24, 35, 36, 30, 3, 42, 14, 10, 29, 16, 50, + + 55, 34, 26, 38, 11, 39, 53, 5, 32, 45, 54, 41, + 35, 2, 51, 14, 15, 23, 36, 3, 8, 16, 21, 42, + 6, 12, 27, 47, 31, 25, 20, 46, 33, 48, 52, 4, + 22, 7, 49, 50, 44, 17, 1, 28, 24, 43, 30, 9, + + 12, 48, 40, 52, 25, 53, 38, 19, 46, 6, 11, 55, + 49, 16, 10, 28, 29, 37, 50, 17, 22, 30, 35, 1, + 20, 26, 41, 4, 45, 39, 34, 31, 47, 5, 13, 18, + 36, 21, 8, 9, 3, 0, 15, 42, 7, 2, 44, 23, + + 26, 5, 54, 13, 39, 38, 52, 33, 31, 20, 25, 12, + 8, 30, 24, 42, 43, 51, 9, 0, 36, 44, 49, 15, + 34, 40, 55, 18, 6, 53, 48, 45, 4, 19, 27, 32, + 50, 35, 22, 23, 17, 14, 29, 1, 21, 16, 3, 37, + + 40, 19, 11, 27, 53, 52, 13, 47, 45, 34, 39, 26, + 22, 44, 7, 1, 2, 10, 23, 14, 50, 3, 8, 29, + 48, 54, 12, 32, 20, 38, 5, 6, 18, 33, 41, 46, + 9, 49, 36, 37, 0, 28, 43, 15, 35, 30, 17, 51, + + 54, 33, 25, 41, 38, 13, 27, 4, 6, 48, 53, 40, + 36, 3, 21, 15, 16, 24, 37, 28, 9, 17, 22, 43, + 5, 11, 26, 46, 34, 52, 19, 20, 32, 47, 55, 31, + 23, 8, 50, 51, 14, 42, 2, 29, 49, 44, 0, 10, + + 11, 47, 39, 55, 52, 27, 41, 18, 20, 5, 38, 54, + 50, 17, 35, 29, 30, 7, 51, 42, 23, 0, 36, 2, + 19, 25, 40, 31, 48, 13, 33, 34, 46, 4, 12, 45, + 37, 22, 9, 10, 28, 1, 16, 43, 8, 3, 14, 24, + + 18, 54, 46, 5, 6, 34, 48, 25, 27, 12, 45, 4, + 2, 24, 42, 36, 37, 14, 3, 49, 30, 7, 43, 9, + 26, 32, 47, 38, 55, 20, 40, 41, 53, 11, 19, 52, + 44, 29, 16, 17, 35, 8, 23, 50, 15, 10, 21, 0, + + 32, 11, 31, 19, 20, 48, 5, 39, 41, 26, 6, 18, + 16, 7, 1, 50, 51, 28, 17, 8, 44, 21, 2, 23, + 40, 46, 4, 52, 12, 34, 54, 55, 38, 25, 33, 13, + 3, 43, 30, 0, 49, 22, 37, 9, 29, 24, 35, 14, + + 46, 25, 45, 33, 34, 5, 19, 53, 55, 40, 20, 32, + 30, 21, 15, 9, 10, 42, 0, 22, 3, 35, 16, 37, + 54, 31, 18, 13, 26, 48, 11, 12, 52, 39, 47, 27, + 17, 2, 44, 14, 8, 36, 51, 23, 43, 7, 49, 28, + + 31, 39, 6, 47, 48, 19, 33, 38, 12, 54, 34, 46, + 44, 35, 29, 23, 24, 1, 14, 36, 17, 49, 30, 51, + 11, 45, 32, 27, 40, 5, 25, 26, 13, 53, 4, 41, + 0, 16, 3, 28, 22, 50, 10, 37, 2, 21, 8, 42, + + 45, 53, 20, 4, 5, 33, 47, 52, 26, 11, 48, 31, + 3, 49, 43, 37, 7, 15, 28, 50, 0, 8, 44, 10, + 25, 6, 46, 41, 54, 19, 39, 40, 27, 38, 18, 55, + 14, 30, 17, 42, 36, 9, 24, 51, 16, 35, 22, 1, + + 6, 38, 34, 18, 19, 47, 4, 13, 40, 25, 5, 45, + 17, 8, 2, 51, 21, 29, 42, 9, 14, 22, 3, 24, + 39, 20, 31, 55, 11, 33, 53, 54, 41, 52, 32, 12, + 28, 44, 0, 1, 50, 23, 7, 10, 30, 49, 36, 15, + + 20, 52, 48, 32, 33, 4, 18, 27, 54, 39, 19, 6, + 0, 22, 16, 10, 35, 43, 1, 23, 28, 36, 17, 7, + 53, 34, 45, 12, 25, 47, 38, 11, 55, 13, 46, 26, + 42, 3, 14, 15, 9, 37, 21, 24, 44, 8, 50, 29, + + 27, 6, 55, 39, 40, 11, 25, 34, 4, 46, 26, 13, + 7, 29, 23, 17, 42, 50, 8, 30, 35, 43, 24, 14, + 31, 41, 52, 19, 32, 54, 45, 18, 5, 20, 53, 33, + 49, 10, 21, 22, 16, 44, 28, 0, 51, 15, 2, 36, +}; + +const static u8 parity[] = { + 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, +}; + + +static void des_small_fips_encrypt(u32 *expkey, u8 *dst, const u8 *src) +{ + u32 x, y, z; + + x = src[7]; + x <<= 8; + x |= src[6]; + x <<= 8; + x |= src[5]; + x <<= 8; + x |= src[4]; + y = src[3]; + y <<= 8; + y |= src[2]; + y <<= 8; + y |= src[1]; + y <<= 8; + y |= src[0]; + z = ((x >> 004) ^ y) & 0x0F0F0F0FL; + x ^= z << 004; + y ^= z; + z = ((y >> 020) ^ x) & 0x0000FFFFL; + y ^= z << 020; + x ^= z; + z = ((x >> 002) ^ y) & 0x33333333L; + x ^= z << 002; + y ^= z; + z = ((y >> 010) ^ x) & 0x00FF00FFL; + y ^= z << 010; + x ^= z; + x = x >> 1 | x << 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y >> 1 | y << 31; + z = expkey[0]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[1]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[2]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[3]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[4]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[5]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[6]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[7]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[8]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[9]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[10]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[11]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[12]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[13]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[14]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[15]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[16]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[17]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[18]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[19]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[20]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[21]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[22]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[23]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[24]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[25]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[26]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[27]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[28]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[29]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[30]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[31]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + x = x << 1 | x >> 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y << 1 | y >> 31; + z = ((x >> 010) ^ y) & 0x00FF00FFL; + x ^= z << 010; + y ^= z; + z = ((y >> 002) ^ x) & 0x33333333L; + y ^= z << 002; + x ^= z; + z = ((x >> 020) ^ y) & 0x0000FFFFL; + x ^= z << 020; + y ^= z; + z = ((y >> 004) ^ x) & 0x0F0F0F0FL; + y ^= z << 004; + x ^= z; + dst[0] = x; + x >>= 8; + dst[1] = x; + x >>= 8; + dst[2] = x; + x >>= 8; + dst[3] = x; + dst[4] = y; + y >>= 8; + dst[5] = y; + y >>= 8; + dst[6] = y; + y >>= 8; + dst[7] = y; +} + +static void des_small_fips_decrypt(u32 *expkey, u8 *dst, const u8 *src) +{ + u32 x, y, z; + + x = src[7]; + x <<= 8; + x |= src[6]; + x <<= 8; + x |= src[5]; + x <<= 8; + x |= src[4]; + y = src[3]; + y <<= 8; + y |= src[2]; + y <<= 8; + y |= src[1]; + y <<= 8; + y |= src[0]; + z = ((x >> 004) ^ y) & 0x0F0F0F0FL; + x ^= z << 004; + y ^= z; + z = ((y >> 020) ^ x) & 0x0000FFFFL; + y ^= z << 020; + x ^= z; + z = ((x >> 002) ^ y) & 0x33333333L; + x ^= z << 002; + y ^= z; + z = ((y >> 010) ^ x) & 0x00FF00FFL; + y ^= z << 010; + x ^= z; + x = x >> 1 | x << 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y >> 1 | y << 31; + z = expkey[31]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[30]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[29]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[28]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[27]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[26]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[25]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[24]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[23]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[22]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[21]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[20]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[19]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[18]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[17]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[16]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[15]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[14]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[13]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[12]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[11]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[10]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[9]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[8]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[7]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[6]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[5]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[4]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[3]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[2]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[1]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[0]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + x = x << 1 | x >> 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y << 1 | y >> 31; + z = ((x >> 010) ^ y) & 0x00FF00FFL; + x ^= z << 010; + y ^= z; + z = ((y >> 002) ^ x) & 0x33333333L; + y ^= z << 002; + x ^= z; + z = ((x >> 020) ^ y) & 0x0000FFFFL; + x ^= z << 020; + y ^= z; + z = ((y >> 004) ^ x) & 0x0F0F0F0FL; + y ^= z << 004; + x ^= z; + dst[0] = x; + x >>= 8; + dst[1] = x; + x >>= 8; + dst[2] = x; + x >>= 8; + dst[3] = x; + dst[4] = y; + y >>= 8; + dst[5] = y; + y >>= 8; + dst[6] = y; + y >>= 8; + dst[7] = y; +} + +/* + * RFC2451: Weak key checks SHOULD be performed. + */ +static int setkey(u32 *expkey, const u8 *key, unsigned int keylen, u32 *flags) +{ + const u8 *k; + u8 *b0, *b1; + u32 n, w; + u8 bits0[56], bits1[56]; + + n = parity[key[0]]; n <<= 4; + n |= parity[key[1]]; n <<= 4; + n |= parity[key[2]]; n <<= 4; + n |= parity[key[3]]; n <<= 4; + n |= parity[key[4]]; n <<= 4; + n |= parity[key[5]]; n <<= 4; + n |= parity[key[6]]; n <<= 4; + n |= parity[key[7]]; + w = 0x88888888L; + + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) + && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */ + if (n < 0x41415151) { + if (n < 0x31312121) { + if (n < 0x14141515) { + /* 01 01 01 01 01 01 01 01 */ + if (n == 0x11111111) goto weak; + /* 01 1F 01 1F 01 0E 01 0E */ + if (n == 0x13131212) goto weak; + } else { + /* 01 E0 01 E0 01 F1 01 F1 */ + if (n == 0x14141515) goto weak; + /* 01 FE 01 FE 01 FE 01 FE */ + if (n == 0x16161616) goto weak; + } + } else { + if (n < 0x34342525) { + /* 1F 01 1F 01 0E 01 0E 01 */ + if (n == 0x31312121) goto weak; + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ + if (n == 0x33332222) goto weak; + } else { + /* 1F E0 1F E0 0E F1 0E F1 */ + if (n == 0x34342525) goto weak; + /* 1F FE 1F FE 0E FE 0E FE */ + if (n == 0x36362626) goto weak; + } + } + } else { + if (n < 0x61616161) { + if (n < 0x44445555) { + /* E0 01 E0 01 F1 01 F1 01 */ + if (n == 0x41415151) goto weak; + /* E0 1F E0 1F F1 0E F1 0E */ + if (n == 0x43435252) goto weak; + } else { + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ + if (n == 0x44445555) goto weak; + /* E0 FE E0 FE F1 FE F1 FE */ + if (n == 0x46465656) goto weak; + } + } else { + if (n < 0x64646565) { + /* FE 01 FE 01 FE 01 FE 01 */ + if (n == 0x61616161) goto weak; + /* FE 1F FE 1F FE 0E FE 0E */ + if (n == 0x63636262) goto weak; + } else { + /* FE E0 FE E0 FE F1 FE F1 */ + if (n == 0x64646565) goto weak; + /* FE FE FE FE FE FE FE FE */ + if (n == 0x66666666) goto weak; + } + } + } + + goto not_weak; +weak: + *flags |= CRYPTO_TFM_RES_WEAK_KEY; + return -EINVAL; + } + +not_weak: + + /* explode the bits */ + n = 56; + b0 = bits0; + b1 = bits1; + + do { + w = (256 | *key++) << 2; + do { + --n; + b1[n] = 8 & w; + w >>= 1; + b0[n] = 4 & w; + } while ( w >= 16 ); + } while ( n ); + + /* put the bits in the correct places */ + n = 16; + k = rotors; + + do { + w = (b1[k[ 0 ]] | b0[k[ 1 ]]) << 4; + w |= (b1[k[ 2 ]] | b0[k[ 3 ]]) << 2; + w |= b1[k[ 4 ]] | b0[k[ 5 ]]; + w <<= 8; + w |= (b1[k[ 6 ]] | b0[k[ 7 ]]) << 4; + w |= (b1[k[ 8 ]] | b0[k[ 9 ]]) << 2; + w |= b1[k[10 ]] | b0[k[11 ]]; + w <<= 8; + w |= (b1[k[12 ]] | b0[k[13 ]]) << 4; + w |= (b1[k[14 ]] | b0[k[15 ]]) << 2; + w |= b1[k[16 ]] | b0[k[17 ]]; + w <<= 8; + w |= (b1[k[18 ]] | b0[k[19 ]]) << 4; + w |= (b1[k[20 ]] | b0[k[21 ]]) << 2; + w |= b1[k[22 ]] | b0[k[23 ]]; + expkey[0] = w; + + w = (b1[k[ 0+24]] | b0[k[ 1+24]]) << 4; + w |= (b1[k[ 2+24]] | b0[k[ 3+24]]) << 2; + w |= b1[k[ 4+24]] | b0[k[ 5+24]]; + w <<= 8; + w |= (b1[k[ 6+24]] | b0[k[ 7+24]]) << 4; + w |= (b1[k[ 8+24]] | b0[k[ 9+24]]) << 2; + w |= b1[k[10+24]] | b0[k[11+24]]; + w <<= 8; + w |= (b1[k[12+24]] | b0[k[13+24]]) << 4; + w |= (b1[k[14+24]] | b0[k[15+24]]) << 2; + w |= b1[k[16+24]] | b0[k[17+24]]; + w <<= 8; + w |= (b1[k[18+24]] | b0[k[19+24]]) << 4; + w |= (b1[k[20+24]] | b0[k[21+24]]) << 2; + w |= b1[k[22+24]] | b0[k[23+24]]; + + ROR(w, 4, 28); /* could be eliminated */ + expkey[1] = w; + + k += 48; + expkey += 2; + } while (--n); + + return 0; +} + +static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + return setkey(((struct des_ctx *)ctx)->expkey, key, keylen, flags); +} + +static void des_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + des_small_fips_encrypt(((struct des_ctx *)ctx)->expkey, dst, src); +} + +static void des_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + des_small_fips_decrypt(((struct des_ctx *)ctx)->expkey, dst, src); +} + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + * + */ +static int des3_ede_setkey(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags) +{ + unsigned int i, off; + struct des3_ede_ctx *dctx = ctx; + + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], + DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + + for (i = 0, off = 0; i < 3; i++, off += DES_EXPKEY_WORDS, + key += DES_KEY_SIZE) { + int ret = setkey(&dctx->expkey[off], key, DES_KEY_SIZE, flags); + if (ret < 0) + return ret; + } + return 0; +} + +static void des3_ede_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct des3_ede_ctx *dctx = ctx; + + des_small_fips_encrypt(dctx->expkey, dst, src); + des_small_fips_decrypt(&dctx->expkey[DES_EXPKEY_WORDS], dst, dst); + des_small_fips_encrypt(&dctx->expkey[DES_EXPKEY_WORDS * 2], dst, dst); +} + +static void des3_ede_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct des3_ede_ctx *dctx = ctx; + + des_small_fips_decrypt(&dctx->expkey[DES_EXPKEY_WORDS * 2], dst, src); + des_small_fips_encrypt(&dctx->expkey[DES_EXPKEY_WORDS], dst, dst); + des_small_fips_decrypt(dctx->expkey, dst, dst); +} + +static struct crypto_alg des_alg = { + .cra_name = "des", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct des_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_ivsize = DES_BLOCK_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt } } +}; + +static struct crypto_alg des3_ede_alg = { + .cra_name = "des3_ede", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct des3_ede_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_ede_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_EDE_KEY_SIZE, + .cia_max_keysize = DES3_EDE_KEY_SIZE, + .cia_ivsize = DES3_EDE_BLOCK_SIZE, + .cia_setkey = des3_ede_setkey, + .cia_encrypt = des3_ede_encrypt, + .cia_decrypt = des3_ede_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&des_alg); + if (ret < 0) + goto out; + + ret = crypto_register_alg(&des3_ede_alg); + if (ret < 0) + crypto_unregister_alg(&des_alg); +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&des3_ede_alg); + crypto_unregister_alg(&des_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); diff -Nru a/crypto/digest.c b/crypto/digest.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/digest.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,82 @@ +/* + * Cryptographic API. + * + * Digest operations. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static void init(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); +} + +static void update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + unsigned int i; + + for (i = 0; i < nsg; i++) { + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), + p, sg[i].length); + crypto_kunmap(p, 0); + crypto_yield(tfm); + } +} + +static void final(struct crypto_tfm *tfm, u8 *out) +{ + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); +} + +static void digest(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg, u8 *out) +{ + unsigned int i; + + tfm->crt_digest.dit_init(tfm); + + for (i = 0; i < nsg; i++) { + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), + p, sg[i].length); + crypto_kunmap(p, 0); + crypto_yield(tfm); + } + crypto_digest_final(tfm, out); +} + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_digest_ops(struct crypto_tfm *tfm) +{ + struct digest_tfm *ops = &tfm->crt_digest; + + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + + return crypto_alloc_hmac_block(tfm); +} + +void crypto_exit_digest_ops(struct crypto_tfm *tfm) +{ + crypto_free_hmac_block(tfm); +} diff -Nru a/crypto/hmac.c b/crypto/hmac.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/hmac.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,134 @@ +/* + * Cryptographic API. + * + * HMAC: Keyed-Hashing for Message Authentication (RFC2104). + * + * Copyright (c) 2002 James Morris + * + * The HMAC implementation is derived from USAGI. + * Copyright (c) 2002 Kazunori Miyazawa / USAGI + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) +{ + struct scatterlist tmp; + + tmp.page = virt_to_page(key); + tmp.offset = ((long)key & ~PAGE_MASK); + tmp.length = keylen; + crypto_digest_digest(tfm, &tmp, 1, key); + +} + +int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + int ret = 0; + + BUG_ON(!crypto_tfm_alg_blocksize(tfm)); + + tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), + GFP_KERNEL); + if (tfm->crt_digest.dit_hmac_block == NULL) + ret = -ENOMEM; + + return ret; + +} + +void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ + if (tfm->crt_digest.dit_hmac_block) + kfree(tfm->crt_digest.dit_hmac_block); +} + +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) +{ + unsigned int i; + struct scatterlist tmp; + char *ipad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } + + memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(ipad, key, *keylen); + + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + ipad[i] ^= 0x36; + + tmp.page = virt_to_page(ipad); + tmp.offset = ((long)ipad & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_blocksize(tfm); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); +} + +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + crypto_digest_update(tfm, sg, nsg); +} + +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out) +{ + unsigned int i; + struct scatterlist tmp; + char *opad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } + + crypto_digest_final(tfm, out); + + memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(opad, key, *keylen); + + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + opad[i] ^= 0x5c; + + tmp.page = virt_to_page(opad); + tmp.offset = ((long)opad & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_blocksize(tfm); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); + + tmp.page = virt_to_page(out); + tmp.offset = ((long)out & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_digestsize(tfm); + + crypto_digest_update(tfm, &tmp, 1); + crypto_digest_final(tfm, out); +} + +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out) +{ + crypto_hmac_init(tfm, key, keylen); + crypto_hmac_update(tfm, sg, nsg); + crypto_hmac_final(tfm, key, keylen, out); +} + +EXPORT_SYMBOL_GPL(crypto_hmac_init); +EXPORT_SYMBOL_GPL(crypto_hmac_update); +EXPORT_SYMBOL_GPL(crypto_hmac_final); +EXPORT_SYMBOL_GPL(crypto_hmac); + diff -Nru a/crypto/internal.h b/crypto/internal.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/internal.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,94 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_INTERNAL_H +#define _CRYPTO_INTERNAL_H +#include +#include +#include +#include +#include +#include + +extern enum km_type crypto_km_types[]; + +static inline enum km_type crypto_kmap_type(int out) +{ + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; +} + +static inline void *crypto_kmap(struct page *page, int out) +{ + return kmap_atomic(page, crypto_kmap_type(out)); +} + +static inline void crypto_kunmap(void *vaddr, int out) +{ + kunmap_atomic(vaddr, crypto_kmap_type(out)); +} + +static inline void crypto_yield(struct crypto_tfm *tfm) +{ + if (!in_softirq()) + cond_resched(); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; +} + +struct crypto_alg *crypto_alg_lookup(const char *name); + +#ifdef CONFIG_KMOD +void crypto_alg_autoload(const char *name); +struct crypto_alg *crypto_alg_mod_lookup(const char *name); +#else +static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + return crypto_alg_lookup(name); +} +#endif + +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + +#ifdef CONFIG_PROC_FS +void __init crypto_init_proc(void); +#else +static inline void crypto_init_proc(void) +{ } +#endif + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); + +int crypto_init_digest_ops(struct crypto_tfm *tfm); +int crypto_init_cipher_ops(struct crypto_tfm *tfm); +int crypto_init_compress_ops(struct crypto_tfm *tfm); + +void crypto_exit_digest_ops(struct crypto_tfm *tfm); +void crypto_exit_cipher_ops(struct crypto_tfm *tfm); +void crypto_exit_compress_ops(struct crypto_tfm *tfm); + +#endif /* _CRYPTO_INTERNAL_H */ + diff -Nru a/crypto/md4.c b/crypto/md4.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/md4.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,250 @@ +/* + * Cryptographic API. + * + * MD4 Message Digest Algorithm (RFC1320). + * + * Implementation derived from Andrew Tridgell and Steve French's + * CIFS MD4 implementation, and the cryptoapi implementation + * originally based on the public domain implementation written + * by Colin Plumb in 1993. + * + * Copyright (c) Andrew Tridgell 1997-1998. + * Modified by Steve French (sfrench@us.ibm.com) 2002 + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define MD4_DIGEST_SIZE 16 +#define MD4_HMAC_BLOCK_SIZE 64 +#define MD4_BLOCK_WORDS 16 +#define MD4_HASH_WORDS 4 + +struct md4_ctx { + u32 hash[MD4_HASH_WORDS]; + u32 block[MD4_BLOCK_WORDS]; + u64 byte_count; +}; + +static inline u32 lshift(u32 x, unsigned int s) +{ + x &= 0xFFFFFFFF; + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); +} + +static inline u32 F(u32 x, u32 y, u32 z) +{ + return (x & y) | ((~x) & z); +} + +static inline u32 G(u32 x, u32 y, u32 z) +{ + return (x & y) | (x & z) | (y & z); +} + +static inline u32 H(u32 x, u32 y, u32 z) +{ + return x ^ y ^ z; +} + +#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) +#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s)) +#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s)) + +/* XXX: this stuff can be optimized */ +static inline void le32_to_cpu_array(u32 *buf, unsigned int words) +{ + while (words--) { + __le32_to_cpus(buf); + buf++; + } +} + +static inline void cpu_to_le32_array(u32 *buf, unsigned int words) +{ + while (words--) { + __cpu_to_le32s(buf); + buf++; + } +} + +static void md4_transform(u32 *hash, u32 const *in) +{ + u32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + ROUND1(a, b, c, d, in[0], 3); + ROUND1(d, a, b, c, in[1], 7); + ROUND1(c, d, a, b, in[2], 11); + ROUND1(b, c, d, a, in[3], 19); + ROUND1(a, b, c, d, in[4], 3); + ROUND1(d, a, b, c, in[5], 7); + ROUND1(c, d, a, b, in[6], 11); + ROUND1(b, c, d, a, in[7], 19); + ROUND1(a, b, c, d, in[8], 3); + ROUND1(d, a, b, c, in[9], 7); + ROUND1(c, d, a, b, in[10], 11); + ROUND1(b, c, d, a, in[11], 19); + ROUND1(a, b, c, d, in[12], 3); + ROUND1(d, a, b, c, in[13], 7); + ROUND1(c, d, a, b, in[14], 11); + ROUND1(b, c, d, a, in[15], 19); + + ROUND2(a, b, c, d,in[ 0], 3); + ROUND2(d, a, b, c, in[4], 5); + ROUND2(c, d, a, b, in[8], 9); + ROUND2(b, c, d, a, in[12], 13); + ROUND2(a, b, c, d, in[1], 3); + ROUND2(d, a, b, c, in[5], 5); + ROUND2(c, d, a, b, in[9], 9); + ROUND2(b, c, d, a, in[13], 13); + ROUND2(a, b, c, d, in[2], 3); + ROUND2(d, a, b, c, in[6], 5); + ROUND2(c, d, a, b, in[10], 9); + ROUND2(b, c, d, a, in[14], 13); + ROUND2(a, b, c, d, in[3], 3); + ROUND2(d, a, b, c, in[7], 5); + ROUND2(c, d, a, b, in[11], 9); + ROUND2(b, c, d, a, in[15], 13); + + ROUND3(a, b, c, d,in[ 0], 3); + ROUND3(d, a, b, c, in[8], 9); + ROUND3(c, d, a, b, in[4], 11); + ROUND3(b, c, d, a, in[12], 15); + ROUND3(a, b, c, d, in[2], 3); + ROUND3(d, a, b, c, in[10], 9); + ROUND3(c, d, a, b, in[6], 11); + ROUND3(b, c, d, a, in[14], 15); + ROUND3(a, b, c, d, in[1], 3); + ROUND3(d, a, b, c, in[9], 9); + ROUND3(c, d, a, b, in[5], 11); + ROUND3(b, c, d, a, in[13], 15); + ROUND3(a, b, c, d, in[3], 3); + ROUND3(d, a, b, c, in[11], 9); + ROUND3(c, d, a, b, in[7], 11); + ROUND3(b, c, d, a, in[15], 15); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +static inline void md4_transform_helper(struct md4_ctx *ctx) +{ + le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); + md4_transform(ctx->hash, ctx->block); +} + +static void md4_init(void *ctx) +{ + struct md4_ctx *mctx = ctx; + + mctx->hash[0] = 0x67452301; + mctx->hash[1] = 0xefcdab89; + mctx->hash[2] = 0x98badcfe; + mctx->hash[3] = 0x10325476; + mctx->byte_count = 0; +} + +static void md4_update(void *ctx, const u8 *data, unsigned int len) +{ + struct md4_ctx *mctx = ctx; + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, avail); + + md4_transform_helper(mctx); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + memcpy(mctx->block, data, sizeof(mctx->block)); + md4_transform_helper(mctx); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + memcpy(mctx->block, data, len); +} + +static void md4_final(void *ctx, u8 *out) +{ + struct md4_ctx *mctx = ctx; + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + + *p++ = 0x80; + if (padding < 0) { + memset(p, 0x00, padding + sizeof (u64)); + md4_transform_helper(mctx); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = mctx->byte_count << 3; + mctx->block[15] = mctx->byte_count >> 29; + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - + sizeof(u64)) / sizeof(u32)); + md4_transform(mctx->hash, mctx->block); + cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(mctx)); +} + +static struct crypto_alg alg = { + .cra_name = "md4", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = MD4_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct md4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = MD4_DIGEST_SIZE, + .dia_init = md4_init, + .dia_update = md4_update, + .dia_final = md4_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD4 Message Digest Algorithm"); + diff -Nru a/crypto/md5.c b/crypto/md5.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/md5.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,244 @@ +/* + * Cryptographic API. + * + * MD5 Message Digest Algorithm (RFC1321). + * + * Derived from cryptoapi implementation, originally based on the + * public domain implementation written by Colin Plumb in 1993. + * + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include + +#define MD5_DIGEST_SIZE 16 +#define MD5_HMAC_BLOCK_SIZE 64 +#define MD5_BLOCK_WORDS 16 +#define MD5_HASH_WORDS 4 + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, in, s) \ + (w += f(x, y, z) + in, w = (w<>(32-s)) + x) + +struct md5_ctx { + u32 hash[MD5_HASH_WORDS]; + u32 block[MD5_BLOCK_WORDS]; + u64 byte_count; +}; + +static void md5_transform(u32 *hash, u32 const *in) +{ + u32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +/* XXX: this stuff can be optimized */ +static inline void le32_to_cpu_array(u32 *buf, unsigned int words) +{ + while (words--) { + __le32_to_cpus(buf); + buf++; + } +} + +static inline void cpu_to_le32_array(u32 *buf, unsigned int words) +{ + while (words--) { + __cpu_to_le32s(buf); + buf++; + } +} + +static inline void md5_transform_helper(struct md5_ctx *ctx) +{ + le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); + md5_transform(ctx->hash, ctx->block); +} + +static void md5_init(void *ctx) +{ + struct md5_ctx *mctx = ctx; + + mctx->hash[0] = 0x67452301; + mctx->hash[1] = 0xefcdab89; + mctx->hash[2] = 0x98badcfe; + mctx->hash[3] = 0x10325476; + mctx->byte_count = 0; +} + +static void md5_update(void *ctx, const u8 *data, unsigned int len) +{ + struct md5_ctx *mctx = ctx; + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, avail); + + md5_transform_helper(mctx); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + memcpy(mctx->block, data, sizeof(mctx->block)); + md5_transform_helper(mctx); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + memcpy(mctx->block, data, len); +} + +static void md5_final(void *ctx, u8 *out) +{ + struct md5_ctx *mctx = ctx; + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + + *p++ = 0x80; + if (padding < 0) { + memset(p, 0x00, padding + sizeof (u64)); + md5_transform_helper(mctx); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = mctx->byte_count << 3; + mctx->block[15] = mctx->byte_count >> 29; + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - + sizeof(u64)) / sizeof(u32)); + md5_transform(mctx->hash, mctx->block); + cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(mctx)); +} + +static struct crypto_alg alg = { + .cra_name = "md5", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct md5_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = MD5_DIGEST_SIZE, + .dia_init = md5_init, + .dia_update = md5_update, + .dia_final = md5_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); diff -Nru a/crypto/proc.c b/crypto/proc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/proc.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,106 @@ +/* + * Scatterlist Cryptographic API. + * + * Procfs information. + * + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + struct list_head *v; + loff_t n = *pos; + + down_read(&crypto_alg_sem); + list_for_each(v, &crypto_alg_list) + if (!n--) + return list_entry(v, struct crypto_alg, cra_list); + return NULL; +} + +static void *c_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct list_head *v = p; + + (*pos)++; + v = v->next; + return (v == &crypto_alg_list) ? + NULL : list_entry(v, struct crypto_alg, cra_list); +} + +static void c_stop(struct seq_file *m, void *p) +{ + up_read(&crypto_alg_sem); +} + +static int c_show(struct seq_file *m, void *p) +{ + struct crypto_alg *alg = (struct crypto_alg *)p; + + seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "module : %s\n", alg->cra_module->name); + + switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_CIPHER: + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "min keysize : %u\n", + alg->cra_cipher.cia_min_keysize); + seq_printf(m, "max keysize : %u\n", + alg->cra_cipher.cia_max_keysize); + seq_printf(m, "ivsize : %u\n", + alg->cra_cipher.cia_ivsize); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "digestsize : %u\n", + alg->cra_digest.dia_digestsize); + break; + } + + seq_putc(m, '\n'); + return 0; +} + +static struct seq_operations crypto_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show +}; + +static int crypto_info_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &crypto_seq_ops); +} + +static struct file_operations proc_crypto_ops = { + .open = crypto_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +void __init crypto_init_proc(void) +{ + struct proc_dir_entry *proc; + + proc = create_proc_entry("crypto", 0, NULL); + if (proc) + proc->proc_fops = &proc_crypto_ops; +} diff -Nru a/crypto/serpent.c b/crypto/serpent.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/serpent.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,507 @@ +/* + * Cryptographic API. + * + * Serpent Cipher Algorithm. + * + * Copyright (C) 2002 Dag Arne Osvik + * + * 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 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +/* Key is padded to the maximum of 256 bits before round key generation. + * Any key length <= 256 bits (32 bytes) is allowed by the algorithm. + */ + +#define SERPENT_MIN_KEY_SIZE 0 +#define SERPENT_MAX_KEY_SIZE 32 +#define SERPENT_EXPKEY_WORDS 132 +#define SERPENT_BLOCK_SIZE 16 + +#define PHI 0x9e3779b9UL +#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r)))) +#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r)))) + +#define keyiter(a,b,c,d,i,j) \ + b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b; + +#define loadkeys(x0,x1,x2,x3,i) \ + x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3]; + +#define storekeys(x0,x1,x2,x3,i) \ + k[i]=x0; k[i+1]=x1; k[i+2]=x2; k[i+3]=x3; + +#define K(x0,x1,x2,x3,i) \ + x3 ^= k[4*(i)+3]; x2 ^= k[4*(i)+2]; \ + x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0]; + +#define LK(x0,x1,x2,x3,x4,i) \ + ROL(x0,13); \ + ROL(x2,3); x1 ^= x0; x4 = x0 << 3; \ + x3 ^= x2; x1 ^= x2; \ + ROL(x1,1); x3 ^= x4; \ + ROL(x3,7); x4 = x1; \ + x0 ^= x1; x4 <<= 7; x2 ^= x3; \ + x0 ^= x3; x2 ^= x4; x3 ^= k[4*i+3]; \ + x1 ^= k[4*i+1]; ROL(x0,5); ROL(x2,22); \ + x0 ^= k[4*i+0]; x2 ^= k[4*i+2]; + +#define KL(x0,x1,x2,x3,x4,i) \ + x0 ^= k[4*i+0]; x1 ^= k[4*i+1]; x2 ^= k[4*i+2]; \ + x3 ^= k[4*i+3]; ROR(x0,5); ROR(x2,22); \ + x4 = x1; x2 ^= x3; x0 ^= x3; \ + x4 <<= 7; x0 ^= x1; ROR(x1,1); \ + x2 ^= x4; ROR(x3,7); x4 = x0 << 3; \ + x1 ^= x0; x3 ^= x4; ROR(x0,13); \ + x1 ^= x2; x3 ^= x2; ROR(x2,3); + +#define S0(x0,x1,x2,x3,x4) \ + x4 = x3; \ + x3 |= x0; x0 ^= x4; x4 ^= x2; \ + x4 =~ x4; x3 ^= x1; x1 &= x0; \ + x1 ^= x4; x2 ^= x0; x0 ^= x3; \ + x4 |= x0; x0 ^= x2; x2 &= x1; \ + x3 ^= x2; x1 =~ x1; x2 ^= x4; \ + x1 ^= x2; + +#define S1(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x1 ^= x0; x0 ^= x3; x3 =~ x3; \ + x4 &= x1; x0 |= x1; x3 ^= x2; \ + x0 ^= x3; x1 ^= x3; x3 ^= x4; \ + x1 |= x4; x4 ^= x2; x2 &= x0; \ + x2 ^= x1; x1 |= x0; x0 =~ x0; \ + x0 ^= x2; x4 ^= x1; + +#define S2(x0,x1,x2,x3,x4) \ + x3 =~ x3; \ + x1 ^= x0; x4 = x0; x0 &= x2; \ + x0 ^= x3; x3 |= x4; x2 ^= x1; \ + x3 ^= x1; x1 &= x0; x0 ^= x2; \ + x2 &= x3; x3 |= x1; x0 =~ x0; \ + x3 ^= x0; x4 ^= x0; x0 ^= x2; \ + x1 |= x2; + +#define S3(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x1 ^= x3; x3 |= x0; x4 &= x0; \ + x0 ^= x2; x2 ^= x1; x1 &= x3; \ + x2 ^= x3; x0 |= x4; x4 ^= x3; \ + x1 ^= x0; x0 &= x3; x3 &= x4; \ + x3 ^= x2; x4 |= x1; x2 &= x1; \ + x4 ^= x3; x0 ^= x3; x3 ^= x2; + +#define S4(x0,x1,x2,x3,x4) \ + x4 = x3; \ + x3 &= x0; x0 ^= x4; \ + x3 ^= x2; x2 |= x4; x0 ^= x1; \ + x4 ^= x3; x2 |= x0; \ + x2 ^= x1; x1 &= x0; \ + x1 ^= x4; x4 &= x2; x2 ^= x3; \ + x4 ^= x0; x3 |= x1; x1 =~ x1; \ + x3 ^= x0; + +#define S5(x0,x1,x2,x3,x4) \ + x4 = x1; x1 |= x0; \ + x2 ^= x1; x3 =~ x3; x4 ^= x0; \ + x0 ^= x2; x1 &= x4; x4 |= x3; \ + x4 ^= x0; x0 &= x3; x1 ^= x3; \ + x3 ^= x2; x0 ^= x1; x2 &= x4; \ + x1 ^= x2; x2 &= x0; \ + x3 ^= x2; + +#define S6(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x3 ^= x0; x1 ^= x2; x2 ^= x0; \ + x0 &= x3; x1 |= x3; x4 =~ x4; \ + x0 ^= x1; x1 ^= x2; \ + x3 ^= x4; x4 ^= x0; x2 &= x0; \ + x4 ^= x1; x2 ^= x3; x3 &= x1; \ + x3 ^= x0; x1 ^= x2; + +#define S7(x0,x1,x2,x3,x4) \ + x1 =~ x1; \ + x4 = x1; x0 =~ x0; x1 &= x2; \ + x1 ^= x3; x3 |= x4; x4 ^= x2; \ + x2 ^= x3; x3 ^= x0; x0 |= x1; \ + x2 &= x0; x0 ^= x4; x4 ^= x3; \ + x3 &= x0; x4 ^= x1; \ + x2 ^= x4; x3 ^= x1; x4 |= x0; \ + x4 ^= x1; + +#define SI0(x0,x1,x2,x3,x4) \ + x4 = x3; x1 ^= x0; \ + x3 |= x1; x4 ^= x1; x0 =~ x0; \ + x2 ^= x3; x3 ^= x0; x0 &= x1; \ + x0 ^= x2; x2 &= x3; x3 ^= x4; \ + x2 ^= x3; x1 ^= x3; x3 &= x0; \ + x1 ^= x0; x0 ^= x2; x4 ^= x3; + +#define SI1(x0,x1,x2,x3,x4) \ + x1 ^= x3; x4 = x0; \ + x0 ^= x2; x2 =~ x2; x4 |= x1; \ + x4 ^= x3; x3 &= x1; x1 ^= x2; \ + x2 &= x4; x4 ^= x1; x1 |= x3; \ + x3 ^= x0; x2 ^= x0; x0 |= x4; \ + x2 ^= x4; x1 ^= x0; \ + x4 ^= x1; + +#define SI2(x0,x1,x2,x3,x4) \ + x2 ^= x1; x4 = x3; x3 =~ x3; \ + x3 |= x2; x2 ^= x4; x4 ^= x0; \ + x3 ^= x1; x1 |= x2; x2 ^= x0; \ + x1 ^= x4; x4 |= x3; x2 ^= x3; \ + x4 ^= x2; x2 &= x1; \ + x2 ^= x3; x3 ^= x4; x4 ^= x0; + +#define SI3(x0,x1,x2,x3,x4) \ + x2 ^= x1; \ + x4 = x1; x1 &= x2; \ + x1 ^= x0; x0 |= x4; x4 ^= x3; \ + x0 ^= x3; x3 |= x1; x1 ^= x2; \ + x1 ^= x3; x0 ^= x2; x2 ^= x3; \ + x3 &= x1; x1 ^= x0; x0 &= x2; \ + x4 ^= x3; x3 ^= x0; x0 ^= x1; + +#define SI4(x0,x1,x2,x3,x4) \ + x2 ^= x3; x4 = x0; x0 &= x1; \ + x0 ^= x2; x2 |= x3; x4 =~ x4; \ + x1 ^= x0; x0 ^= x2; x2 &= x4; \ + x2 ^= x0; x0 |= x4; \ + x0 ^= x3; x3 &= x2; \ + x4 ^= x3; x3 ^= x1; x1 &= x0; \ + x4 ^= x1; x0 ^= x3; + +#define SI5(x0,x1,x2,x3,x4) \ + x4 = x1; x1 |= x2; \ + x2 ^= x4; x1 ^= x3; x3 &= x4; \ + x2 ^= x3; x3 |= x0; x0 =~ x0; \ + x3 ^= x2; x2 |= x0; x4 ^= x1; \ + x2 ^= x4; x4 &= x0; x0 ^= x1; \ + x1 ^= x3; x0 &= x2; x2 ^= x3; \ + x0 ^= x2; x2 ^= x4; x4 ^= x3; + +#define SI6(x0,x1,x2,x3,x4) \ + x0 ^= x2; \ + x4 = x0; x0 &= x3; x2 ^= x3; \ + x0 ^= x2; x3 ^= x1; x2 |= x4; \ + x2 ^= x3; x3 &= x0; x0 =~ x0; \ + x3 ^= x1; x1 &= x2; x4 ^= x0; \ + x3 ^= x4; x4 ^= x2; x0 ^= x1; \ + x2 ^= x0; + +#define SI7(x0,x1,x2,x3,x4) \ + x4 = x3; x3 &= x0; x0 ^= x2; \ + x2 |= x4; x4 ^= x1; x0 =~ x0; \ + x1 |= x3; x4 ^= x0; x0 &= x2; \ + x0 ^= x1; x1 &= x2; x3 ^= x2; \ + x4 ^= x3; x2 &= x3; x3 |= x0; \ + x1 ^= x4; x3 ^= x4; x4 &= x0; \ + x4 ^= x2; + +struct serpent_ctx { + u8 iv[SERPENT_BLOCK_SIZE]; + u32 expkey[SERPENT_EXPKEY_WORDS]; +}; + +static int setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + u32 *k = ((struct serpent_ctx *)ctx)->expkey; + u8 *k8 = (u8 *)k; + u32 r0,r1,r2,r3,r4; + int i; + + if ((keylen < SERPENT_MIN_KEY_SIZE) + || (keylen > SERPENT_MAX_KEY_SIZE)) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* Copy key, add padding */ + + for (i = 0; i < keylen; ++i) + k8[i] = key[i]; + if (i < SERPENT_MAX_KEY_SIZE) + k8[i++] = 1; + while (i < SERPENT_MAX_KEY_SIZE) + k8[i++] = 0; + + /* Expand key using polynomial */ + + r0 = le32_to_cpu(k[3]); + r1 = le32_to_cpu(k[4]); + r2 = le32_to_cpu(k[5]); + r3 = le32_to_cpu(k[6]); + r4 = le32_to_cpu(k[7]); + + keyiter(le32_to_cpu(k[0]),r0,r4,r2,0,0); + keyiter(le32_to_cpu(k[1]),r1,r0,r3,1,1); + keyiter(le32_to_cpu(k[2]),r2,r1,r4,2,2); + keyiter(le32_to_cpu(k[3]),r3,r2,r0,3,3); + keyiter(le32_to_cpu(k[4]),r4,r3,r1,4,4); + keyiter(le32_to_cpu(k[5]),r0,r4,r2,5,5); + keyiter(le32_to_cpu(k[6]),r1,r0,r3,6,6); + keyiter(le32_to_cpu(k[7]),r2,r1,r4,7,7); + + keyiter(k[ 0],r3,r2,r0, 8, 8); keyiter(k[ 1],r4,r3,r1, 9, 9); + keyiter(k[ 2],r0,r4,r2, 10, 10); keyiter(k[ 3],r1,r0,r3, 11, 11); + keyiter(k[ 4],r2,r1,r4, 12, 12); keyiter(k[ 5],r3,r2,r0, 13, 13); + keyiter(k[ 6],r4,r3,r1, 14, 14); keyiter(k[ 7],r0,r4,r2, 15, 15); + keyiter(k[ 8],r1,r0,r3, 16, 16); keyiter(k[ 9],r2,r1,r4, 17, 17); + keyiter(k[ 10],r3,r2,r0, 18, 18); keyiter(k[ 11],r4,r3,r1, 19, 19); + keyiter(k[ 12],r0,r4,r2, 20, 20); keyiter(k[ 13],r1,r0,r3, 21, 21); + keyiter(k[ 14],r2,r1,r4, 22, 22); keyiter(k[ 15],r3,r2,r0, 23, 23); + keyiter(k[ 16],r4,r3,r1, 24, 24); keyiter(k[ 17],r0,r4,r2, 25, 25); + keyiter(k[ 18],r1,r0,r3, 26, 26); keyiter(k[ 19],r2,r1,r4, 27, 27); + keyiter(k[ 20],r3,r2,r0, 28, 28); keyiter(k[ 21],r4,r3,r1, 29, 29); + keyiter(k[ 22],r0,r4,r2, 30, 30); keyiter(k[ 23],r1,r0,r3, 31, 31); + + k += 50; + + keyiter(k[-26],r2,r1,r4, 32,-18); keyiter(k[-25],r3,r2,r0, 33,-17); + keyiter(k[-24],r4,r3,r1, 34,-16); keyiter(k[-23],r0,r4,r2, 35,-15); + keyiter(k[-22],r1,r0,r3, 36,-14); keyiter(k[-21],r2,r1,r4, 37,-13); + keyiter(k[-20],r3,r2,r0, 38,-12); keyiter(k[-19],r4,r3,r1, 39,-11); + keyiter(k[-18],r0,r4,r2, 40,-10); keyiter(k[-17],r1,r0,r3, 41, -9); + keyiter(k[-16],r2,r1,r4, 42, -8); keyiter(k[-15],r3,r2,r0, 43, -7); + keyiter(k[-14],r4,r3,r1, 44, -6); keyiter(k[-13],r0,r4,r2, 45, -5); + keyiter(k[-12],r1,r0,r3, 46, -4); keyiter(k[-11],r2,r1,r4, 47, -3); + keyiter(k[-10],r3,r2,r0, 48, -2); keyiter(k[ -9],r4,r3,r1, 49, -1); + keyiter(k[ -8],r0,r4,r2, 50, 0); keyiter(k[ -7],r1,r0,r3, 51, 1); + keyiter(k[ -6],r2,r1,r4, 52, 2); keyiter(k[ -5],r3,r2,r0, 53, 3); + keyiter(k[ -4],r4,r3,r1, 54, 4); keyiter(k[ -3],r0,r4,r2, 55, 5); + keyiter(k[ -2],r1,r0,r3, 56, 6); keyiter(k[ -1],r2,r1,r4, 57, 7); + keyiter(k[ 0],r3,r2,r0, 58, 8); keyiter(k[ 1],r4,r3,r1, 59, 9); + keyiter(k[ 2],r0,r4,r2, 60, 10); keyiter(k[ 3],r1,r0,r3, 61, 11); + keyiter(k[ 4],r2,r1,r4, 62, 12); keyiter(k[ 5],r3,r2,r0, 63, 13); + keyiter(k[ 6],r4,r3,r1, 64, 14); keyiter(k[ 7],r0,r4,r2, 65, 15); + keyiter(k[ 8],r1,r0,r3, 66, 16); keyiter(k[ 9],r2,r1,r4, 67, 17); + keyiter(k[ 10],r3,r2,r0, 68, 18); keyiter(k[ 11],r4,r3,r1, 69, 19); + keyiter(k[ 12],r0,r4,r2, 70, 20); keyiter(k[ 13],r1,r0,r3, 71, 21); + keyiter(k[ 14],r2,r1,r4, 72, 22); keyiter(k[ 15],r3,r2,r0, 73, 23); + keyiter(k[ 16],r4,r3,r1, 74, 24); keyiter(k[ 17],r0,r4,r2, 75, 25); + keyiter(k[ 18],r1,r0,r3, 76, 26); keyiter(k[ 19],r2,r1,r4, 77, 27); + keyiter(k[ 20],r3,r2,r0, 78, 28); keyiter(k[ 21],r4,r3,r1, 79, 29); + keyiter(k[ 22],r0,r4,r2, 80, 30); keyiter(k[ 23],r1,r0,r3, 81, 31); + + k += 50; + + keyiter(k[-26],r2,r1,r4, 82,-18); keyiter(k[-25],r3,r2,r0, 83,-17); + keyiter(k[-24],r4,r3,r1, 84,-16); keyiter(k[-23],r0,r4,r2, 85,-15); + keyiter(k[-22],r1,r0,r3, 86,-14); keyiter(k[-21],r2,r1,r4, 87,-13); + keyiter(k[-20],r3,r2,r0, 88,-12); keyiter(k[-19],r4,r3,r1, 89,-11); + keyiter(k[-18],r0,r4,r2, 90,-10); keyiter(k[-17],r1,r0,r3, 91, -9); + keyiter(k[-16],r2,r1,r4, 92, -8); keyiter(k[-15],r3,r2,r0, 93, -7); + keyiter(k[-14],r4,r3,r1, 94, -6); keyiter(k[-13],r0,r4,r2, 95, -5); + keyiter(k[-12],r1,r0,r3, 96, -4); keyiter(k[-11],r2,r1,r4, 97, -3); + keyiter(k[-10],r3,r2,r0, 98, -2); keyiter(k[ -9],r4,r3,r1, 99, -1); + keyiter(k[ -8],r0,r4,r2,100, 0); keyiter(k[ -7],r1,r0,r3,101, 1); + keyiter(k[ -6],r2,r1,r4,102, 2); keyiter(k[ -5],r3,r2,r0,103, 3); + keyiter(k[ -4],r4,r3,r1,104, 4); keyiter(k[ -3],r0,r4,r2,105, 5); + keyiter(k[ -2],r1,r0,r3,106, 6); keyiter(k[ -1],r2,r1,r4,107, 7); + keyiter(k[ 0],r3,r2,r0,108, 8); keyiter(k[ 1],r4,r3,r1,109, 9); + keyiter(k[ 2],r0,r4,r2,110, 10); keyiter(k[ 3],r1,r0,r3,111, 11); + keyiter(k[ 4],r2,r1,r4,112, 12); keyiter(k[ 5],r3,r2,r0,113, 13); + keyiter(k[ 6],r4,r3,r1,114, 14); keyiter(k[ 7],r0,r4,r2,115, 15); + keyiter(k[ 8],r1,r0,r3,116, 16); keyiter(k[ 9],r2,r1,r4,117, 17); + keyiter(k[ 10],r3,r2,r0,118, 18); keyiter(k[ 11],r4,r3,r1,119, 19); + keyiter(k[ 12],r0,r4,r2,120, 20); keyiter(k[ 13],r1,r0,r3,121, 21); + keyiter(k[ 14],r2,r1,r4,122, 22); keyiter(k[ 15],r3,r2,r0,123, 23); + keyiter(k[ 16],r4,r3,r1,124, 24); keyiter(k[ 17],r0,r4,r2,125, 25); + keyiter(k[ 18],r1,r0,r3,126, 26); keyiter(k[ 19],r2,r1,r4,127, 27); + keyiter(k[ 20],r3,r2,r0,128, 28); keyiter(k[ 21],r4,r3,r1,129, 29); + keyiter(k[ 22],r0,r4,r2,130, 30); keyiter(k[ 23],r1,r0,r3,131, 31); + + /* Apply S-boxes */ + + S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 28); loadkeys(r1,r2,r4,r3, 24); + S4(r1,r2,r4,r3,r0); storekeys(r2,r4,r3,r0, 24); loadkeys(r2,r4,r3,r0, 20); + S5(r2,r4,r3,r0,r1); storekeys(r1,r2,r4,r0, 20); loadkeys(r1,r2,r4,r0, 16); + S6(r1,r2,r4,r0,r3); storekeys(r4,r3,r2,r0, 16); loadkeys(r4,r3,r2,r0, 12); + S7(r4,r3,r2,r0,r1); storekeys(r1,r2,r0,r4, 12); loadkeys(r1,r2,r0,r4, 8); + S0(r1,r2,r0,r4,r3); storekeys(r0,r2,r4,r1, 8); loadkeys(r0,r2,r4,r1, 4); + S1(r0,r2,r4,r1,r3); storekeys(r3,r4,r1,r0, 4); loadkeys(r3,r4,r1,r0, 0); + S2(r3,r4,r1,r0,r2); storekeys(r2,r4,r3,r0, 0); loadkeys(r2,r4,r3,r0, -4); + S3(r2,r4,r3,r0,r1); storekeys(r0,r1,r4,r2, -4); loadkeys(r0,r1,r4,r2, -8); + S4(r0,r1,r4,r2,r3); storekeys(r1,r4,r2,r3, -8); loadkeys(r1,r4,r2,r3,-12); + S5(r1,r4,r2,r3,r0); storekeys(r0,r1,r4,r3,-12); loadkeys(r0,r1,r4,r3,-16); + S6(r0,r1,r4,r3,r2); storekeys(r4,r2,r1,r3,-16); loadkeys(r4,r2,r1,r3,-20); + S7(r4,r2,r1,r3,r0); storekeys(r0,r1,r3,r4,-20); loadkeys(r0,r1,r3,r4,-24); + S0(r0,r1,r3,r4,r2); storekeys(r3,r1,r4,r0,-24); loadkeys(r3,r1,r4,r0,-28); + k -= 50; + S1(r3,r1,r4,r0,r2); storekeys(r2,r4,r0,r3, 22); loadkeys(r2,r4,r0,r3, 18); + S2(r2,r4,r0,r3,r1); storekeys(r1,r4,r2,r3, 18); loadkeys(r1,r4,r2,r3, 14); + S3(r1,r4,r2,r3,r0); storekeys(r3,r0,r4,r1, 14); loadkeys(r3,r0,r4,r1, 10); + S4(r3,r0,r4,r1,r2); storekeys(r0,r4,r1,r2, 10); loadkeys(r0,r4,r1,r2, 6); + S5(r0,r4,r1,r2,r3); storekeys(r3,r0,r4,r2, 6); loadkeys(r3,r0,r4,r2, 2); + S6(r3,r0,r4,r2,r1); storekeys(r4,r1,r0,r2, 2); loadkeys(r4,r1,r0,r2, -2); + S7(r4,r1,r0,r2,r3); storekeys(r3,r0,r2,r4, -2); loadkeys(r3,r0,r2,r4, -6); + S0(r3,r0,r2,r4,r1); storekeys(r2,r0,r4,r3, -6); loadkeys(r2,r0,r4,r3,-10); + S1(r2,r0,r4,r3,r1); storekeys(r1,r4,r3,r2,-10); loadkeys(r1,r4,r3,r2,-14); + S2(r1,r4,r3,r2,r0); storekeys(r0,r4,r1,r2,-14); loadkeys(r0,r4,r1,r2,-18); + S3(r0,r4,r1,r2,r3); storekeys(r2,r3,r4,r0,-18); loadkeys(r2,r3,r4,r0,-22); + k -= 50; + S4(r2,r3,r4,r0,r1); storekeys(r3,r4,r0,r1, 28); loadkeys(r3,r4,r0,r1, 24); + S5(r3,r4,r0,r1,r2); storekeys(r2,r3,r4,r1, 24); loadkeys(r2,r3,r4,r1, 20); + S6(r2,r3,r4,r1,r0); storekeys(r4,r0,r3,r1, 20); loadkeys(r4,r0,r3,r1, 16); + S7(r4,r0,r3,r1,r2); storekeys(r2,r3,r1,r4, 16); loadkeys(r2,r3,r1,r4, 12); + S0(r2,r3,r1,r4,r0); storekeys(r1,r3,r4,r2, 12); loadkeys(r1,r3,r4,r2, 8); + S1(r1,r3,r4,r2,r0); storekeys(r0,r4,r2,r1, 8); loadkeys(r0,r4,r2,r1, 4); + S2(r0,r4,r2,r1,r3); storekeys(r3,r4,r0,r1, 4); loadkeys(r3,r4,r0,r1, 0); + S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 0); + + return 0; +} + +static void encrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 + *k = ((struct serpent_ctx *)ctx)->expkey, + *s = (const u32 *)src; + u32 *d = (u32 *)dst, + r0, r1, r2, r3, r4; + +/* + * Note: The conversions between u8* and u32* might cause trouble + * on architectures with stricter alignment rules than x86 + */ + + r0 = le32_to_cpu(s[0]); + r1 = le32_to_cpu(s[1]); + r2 = le32_to_cpu(s[2]); + r3 = le32_to_cpu(s[3]); + + K(r0,r1,r2,r3,0); + S0(r0,r1,r2,r3,r4); LK(r2,r1,r3,r0,r4,1); + S1(r2,r1,r3,r0,r4); LK(r4,r3,r0,r2,r1,2); + S2(r4,r3,r0,r2,r1); LK(r1,r3,r4,r2,r0,3); + S3(r1,r3,r4,r2,r0); LK(r2,r0,r3,r1,r4,4); + S4(r2,r0,r3,r1,r4); LK(r0,r3,r1,r4,r2,5); + S5(r0,r3,r1,r4,r2); LK(r2,r0,r3,r4,r1,6); + S6(r2,r0,r3,r4,r1); LK(r3,r1,r0,r4,r2,7); + S7(r3,r1,r0,r4,r2); LK(r2,r0,r4,r3,r1,8); + S0(r2,r0,r4,r3,r1); LK(r4,r0,r3,r2,r1,9); + S1(r4,r0,r3,r2,r1); LK(r1,r3,r2,r4,r0,10); + S2(r1,r3,r2,r4,r0); LK(r0,r3,r1,r4,r2,11); + S3(r0,r3,r1,r4,r2); LK(r4,r2,r3,r0,r1,12); + S4(r4,r2,r3,r0,r1); LK(r2,r3,r0,r1,r4,13); + S5(r2,r3,r0,r1,r4); LK(r4,r2,r3,r1,r0,14); + S6(r4,r2,r3,r1,r0); LK(r3,r0,r2,r1,r4,15); + S7(r3,r0,r2,r1,r4); LK(r4,r2,r1,r3,r0,16); + S0(r4,r2,r1,r3,r0); LK(r1,r2,r3,r4,r0,17); + S1(r1,r2,r3,r4,r0); LK(r0,r3,r4,r1,r2,18); + S2(r0,r3,r4,r1,r2); LK(r2,r3,r0,r1,r4,19); + S3(r2,r3,r0,r1,r4); LK(r1,r4,r3,r2,r0,20); + S4(r1,r4,r3,r2,r0); LK(r4,r3,r2,r0,r1,21); + S5(r4,r3,r2,r0,r1); LK(r1,r4,r3,r0,r2,22); + S6(r1,r4,r3,r0,r2); LK(r3,r2,r4,r0,r1,23); + S7(r3,r2,r4,r0,r1); LK(r1,r4,r0,r3,r2,24); + S0(r1,r4,r0,r3,r2); LK(r0,r4,r3,r1,r2,25); + S1(r0,r4,r3,r1,r2); LK(r2,r3,r1,r0,r4,26); + S2(r2,r3,r1,r0,r4); LK(r4,r3,r2,r0,r1,27); + S3(r4,r3,r2,r0,r1); LK(r0,r1,r3,r4,r2,28); + S4(r0,r1,r3,r4,r2); LK(r1,r3,r4,r2,r0,29); + S5(r1,r3,r4,r2,r0); LK(r0,r1,r3,r2,r4,30); + S6(r0,r1,r3,r2,r4); LK(r3,r4,r1,r2,r0,31); + S7(r3,r4,r1,r2,r0); K(r0,r1,r2,r3,32); + + d[0] = cpu_to_le32(r0); + d[1] = cpu_to_le32(r1); + d[2] = cpu_to_le32(r2); + d[3] = cpu_to_le32(r3); +} + +static void decrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 + *k = ((struct serpent_ctx *)ctx)->expkey, + *s = (const u32 *)src; + u32 *d = (u32 *)dst, + r0, r1, r2, r3, r4; + + r0 = le32_to_cpu(s[0]); + r1 = le32_to_cpu(s[1]); + r2 = le32_to_cpu(s[2]); + r3 = le32_to_cpu(s[3]); + + K(r0,r1,r2,r3,32); + SI7(r0,r1,r2,r3,r4); KL(r1,r3,r0,r4,r2,31); + SI6(r1,r3,r0,r4,r2); KL(r0,r2,r4,r1,r3,30); + SI5(r0,r2,r4,r1,r3); KL(r2,r3,r0,r4,r1,29); + SI4(r2,r3,r0,r4,r1); KL(r2,r0,r1,r4,r3,28); + SI3(r2,r0,r1,r4,r3); KL(r1,r2,r3,r4,r0,27); + SI2(r1,r2,r3,r4,r0); KL(r2,r0,r4,r3,r1,26); + SI1(r2,r0,r4,r3,r1); KL(r1,r0,r4,r3,r2,25); + SI0(r1,r0,r4,r3,r2); KL(r4,r2,r0,r1,r3,24); + SI7(r4,r2,r0,r1,r3); KL(r2,r1,r4,r3,r0,23); + SI6(r2,r1,r4,r3,r0); KL(r4,r0,r3,r2,r1,22); + SI5(r4,r0,r3,r2,r1); KL(r0,r1,r4,r3,r2,21); + SI4(r0,r1,r4,r3,r2); KL(r0,r4,r2,r3,r1,20); + SI3(r0,r4,r2,r3,r1); KL(r2,r0,r1,r3,r4,19); + SI2(r2,r0,r1,r3,r4); KL(r0,r4,r3,r1,r2,18); + SI1(r0,r4,r3,r1,r2); KL(r2,r4,r3,r1,r0,17); + SI0(r2,r4,r3,r1,r0); KL(r3,r0,r4,r2,r1,16); + SI7(r3,r0,r4,r2,r1); KL(r0,r2,r3,r1,r4,15); + SI6(r0,r2,r3,r1,r4); KL(r3,r4,r1,r0,r2,14); + SI5(r3,r4,r1,r0,r2); KL(r4,r2,r3,r1,r0,13); + SI4(r4,r2,r3,r1,r0); KL(r4,r3,r0,r1,r2,12); + SI3(r4,r3,r0,r1,r2); KL(r0,r4,r2,r1,r3,11); + SI2(r0,r4,r2,r1,r3); KL(r4,r3,r1,r2,r0,10); + SI1(r4,r3,r1,r2,r0); KL(r0,r3,r1,r2,r4,9); + SI0(r0,r3,r1,r2,r4); KL(r1,r4,r3,r0,r2,8); + SI7(r1,r4,r3,r0,r2); KL(r4,r0,r1,r2,r3,7); + SI6(r4,r0,r1,r2,r3); KL(r1,r3,r2,r4,r0,6); + SI5(r1,r3,r2,r4,r0); KL(r3,r0,r1,r2,r4,5); + SI4(r3,r0,r1,r2,r4); KL(r3,r1,r4,r2,r0,4); + SI3(r3,r1,r4,r2,r0); KL(r4,r3,r0,r2,r1,3); + SI2(r4,r3,r0,r2,r1); KL(r3,r1,r2,r0,r4,2); + SI1(r3,r1,r2,r0,r4); KL(r4,r1,r2,r0,r3,1); + SI0(r4,r1,r2,r0,r3); K(r2,r3,r1,r4,0); + + d[0] = cpu_to_le32(r2); + d[1] = cpu_to_le32(r3); + d[2] = cpu_to_le32(r1); + d[3] = cpu_to_le32(r4); +} + +static struct crypto_alg serpent_alg = { + .cra_name = "serpent", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = SERPENT_MIN_KEY_SIZE, + .cia_max_keysize = SERPENT_MAX_KEY_SIZE, + .cia_ivsize = SERPENT_BLOCK_SIZE, + .cia_setkey = setkey, + .cia_encrypt = encrypt, + .cia_decrypt = decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&serpent_alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&serpent_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Serpent Cipher Algorithm"); +MODULE_AUTHOR("Dag Arne Osvik "); diff -Nru a/crypto/sha1.c b/crypto/sha1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/sha1.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,208 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_HMAC_BLOCK_SIZE 64 + +static inline u32 rol(u32 value, u32 bits) +{ + return (((value) << (bits)) | ((value) >> (32 - (bits)))); +} + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +# define blk0(i) block32[i] + +#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \ + ^block32[(i+2)&15]^block32[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \ + w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +struct sha1_ctx { + u64 count; + u32 state[5]; + u8 buffer[64]; +}; + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void sha1_transform(u32 *state, const u8 *in) +{ + u32 a, b, c, d, e; + u32 block32[16]; + + /* convert/copy data to workspace */ + for (a = 0; a < sizeof(block32)/sizeof(u32); a++) + block32[a] = be32_to_cpu (((const u32 *)in)[a]); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; + memset (block32, 0x00, sizeof block32); +} + +static void sha1_init(void *ctx) +{ + struct sha1_ctx *sctx = ctx; + static const struct sha1_ctx initstate = { + 0, + { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, + { 0, } + }; + + *sctx = initstate; +} + +static void sha1_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha1_ctx *sctx = ctx; + unsigned int i, j; + + j = (sctx->count >> 3) & 0x3f; + sctx->count += len << 3; + + if ((j + len) > 63) { + memcpy(&sctx->buffer[j], data, (i = 64-j)); + sha1_transform(sctx->state, sctx->buffer); + for ( ; i + 63 < len; i += 64) { + sha1_transform(sctx->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&sctx->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ +static void sha1_final(void* ctx, u8 *out) +{ + struct sha1_ctx *sctx = ctx; + u32 i, j, index, padlen; + u64 t; + u8 bits[8] = { 0, }; + static const u8 padding[64] = { 0x80, }; + + t = sctx->count; + bits[7] = 0xff & t; t>>=8; + bits[6] = 0xff & t; t>>=8; + bits[5] = 0xff & t; t>>=8; + bits[4] = 0xff & t; t>>=8; + bits[3] = 0xff & t; t>>=8; + bits[2] = 0xff & t; t>>=8; + bits[1] = 0xff & t; t>>=8; + bits[0] = 0xff & t; + + /* Pad out to 56 mod 64 */ + index = (sctx->count >> 3) & 0x3f; + padlen = (index < 56) ? (56 - index) : ((64+56) - index); + sha1_update(sctx, padding, padlen); + + /* Append length */ + sha1_update(sctx, bits, sizeof bits); + + /* Store state in digest */ + for (i = j = 0; i < 5; i++, j += 4) { + u32 t2 = sctx->state[i]; + out[j+3] = t2 & 0xff; t2>>=8; + out[j+2] = t2 & 0xff; t2>>=8; + out[j+1] = t2 & 0xff; t2>>=8; + out[j ] = t2 & 0xff; + } + + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha1", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha1_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA1_DIGEST_SIZE, + .dia_init = sha1_init, + .dia_update = sha1_update, + .dia_final = sha1_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); diff -Nru a/crypto/sha256.c b/crypto/sha256.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/sha256.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,362 @@ +/* + * Cryptographic API. + * + * SHA-256, as specified in + * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf + * + * SHA-256 code by Jean-Luc Cooke . + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2002 James Morris + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_HMAC_BLOCK_SIZE 64 + +struct sha256_ctx { + u32 count[2]; + u32 state[8]; + u8 buf[128]; +}; + +static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return ((x & y) ^ (~x & z)); +} + +static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u32 RORu32(u32 x, u32 y) +{ + return (x >> y) | (x << (32 - y)); +} + +#define e0(x) (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22)) +#define e1(x) (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25)) +#define s0(x) (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3)) +#define s1(x) (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10)) + +#define H0 0x6a09e667 +#define H1 0xbb67ae85 +#define H2 0x3c6ef372 +#define H3 0xa54ff53a +#define H4 0x510e527f +#define H5 0x9b05688c +#define H6 0x1f83d9ab +#define H7 0x5be0cd19 + +static inline void LOAD_OP(int I, u32 *W, const u8 *input) +{ + u32 t1 = input[(4 * I)] & 0xff; + + t1 <<= 8; + t1 |= input[(4 * I) + 1] & 0xff; + t1 <<= 8; + t1 |= input[(4 * I) + 2] & 0xff; + t1 <<= 8; + t1 |= input[(4 * I) + 3] & 0xff; + W[I] = t1; +} + +static inline void BLEND_OP(int I, u32 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void sha256_transform(u32 *state, const u8 *input) +{ + u32 a, b, c, d, e, f, g, h, t1, t2; + u32 W[64]; + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + /* now blend */ + for (i = 16; i < 64; i++) + BLEND_OP(i, W); + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* clear any sensitive info... */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 64 * sizeof(u32)); +} + +static void sha256_init(void *ctx) +{ + struct sha256_ctx *sctx = ctx; + sctx->state[0] = H0; + sctx->state[1] = H1; + sctx->state[2] = H2; + sctx->state[3] = H3; + sctx->state[4] = H4; + sctx->state[5] = H5; + sctx->state[6] = H6; + sctx->state[7] = H7; + sctx->count[0] = sctx->count[1] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void sha256_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha256_ctx *sctx = ctx; + unsigned int i, index, part_len; + + /* Compute number of bytes mod 128 */ + index = (unsigned int)((sctx->count[0] >> 3) & 0x3f); + + /* Update number of bits */ + if ((sctx->count[0] += (len << 3)) < (len << 3)) { + sctx->count[1]++; + sctx->count[1] += (len >> 29); + } + + part_len = 64 - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + sha256_transform(sctx->state, sctx->buf); + + for (i = part_len; i + 63 < len; i += 64) + sha256_transform(sctx->state, &data[i]); + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&sctx->buf[index], &data[i], len-i); +} + +static void sha256_final(void* ctx, u8 *out) +{ + struct sha256_ctx *sctx = ctx; + u8 bits[8]; + unsigned int index, pad_len, t; + int i, j; + const u8 padding[64] = { 0x80, }; + + /* Save number of bits */ + t = sctx->count[0]; + bits[7] = t; t >>= 8; + bits[6] = t; t >>= 8; + bits[5] = t; t >>= 8; + bits[4] = t; + t = sctx->count[1]; + bits[3] = t; t >>= 8; + bits[2] = t; t >>= 8; + bits[1] = t; t >>= 8; + bits[0] = t; + + /* Pad out to 56 mod 64. */ + index = (sctx->count[0] >> 3) & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64+56) - index); + sha256_update(sctx, padding, pad_len); + + /* Append length (before padding) */ + sha256_update(sctx, bits, 8); + + /* Store state in digest */ + for (i = j = 0; i < 8; i++, j += 4) { + t = sctx->state[i]; + out[j+3] = t; t >>= 8; + out[j+2] = t; t >>= 8; + out[j+1] = t; t >>= 8; + out[j ] = t; + } + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(*sctx)); +} + + +static struct crypto_alg alg = { + .cra_name = "sha256", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha256_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA256_DIGEST_SIZE, + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); diff -Nru a/crypto/sha512.c b/crypto/sha512.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/sha512.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,373 @@ +/* SHA-512 code by Jean-Luc Cooke + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2003 Kyle McMartin + * + * 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 2, or (at your option) any + * later version. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 +#define SHA384_HMAC_BLOCK_SIZE 96 +#define SHA512_HMAC_BLOCK_SIZE 128 + +struct sha512_ctx { + u64 state[8]; + u32 count[4]; + u8 buf[128]; +}; + +static inline u64 Ch(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (~x & z)); +} + +static inline u64 Maj(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 RORu64(u64 x, u64 y) +{ + return (x >> y) | (x << (64 - y)); +} + +const u64 sha512_K[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, + 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, + 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, + 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, + 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, + 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, +}; + +#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) +#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) +#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) +#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) + +/* H* initial state for SHA-512 */ +#define H0 0x6a09e667f3bcc908 +#define H1 0xbb67ae8584caa73b +#define H2 0x3c6ef372fe94f82b +#define H3 0xa54ff53a5f1d36f1 +#define H4 0x510e527fade682d1 +#define H5 0x9b05688c2b3e6c1f +#define H6 0x1f83d9abfb41bd6b +#define H7 0x5be0cd19137e2179 + +/* H'* initial state for SHA-384 */ +#define HP0 0xcbbb9d5dc1059ed8 +#define HP1 0x629a292a367cd507 +#define HP2 0x9159015a3070dd17 +#define HP3 0x152fecd8f70e5939 +#define HP4 0x67332667ffc00b31 +#define HP5 0x8eb44a8768581511 +#define HP6 0xdb0c2e0d64f98fa7 +#define HP7 0x47b5481dbefa4fa4 + +static inline void LOAD_OP(int I, u64 *W, const u8 *input) +{ + u64 t1 = input[(8*I) ] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+1] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+2] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+3] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+4] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+5] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+6] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+7] & 0xff; + W[I] = t1; +} + +static inline void BLEND_OP(int I, u64 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void +sha512_transform(u64 *state, const u8 *input) +{ + u64 a, b, c, d, e, f, g, h, t1, t2; + u64 W[80]; + + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + for (i = 16; i < 80; i++) { + BLEND_OP(i, W); + } + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 80 * sizeof(u64)); +} + +static void +sha512_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = H0; + sctx->state[1] = H1; + sctx->state[2] = H2; + sctx->state[3] = H3; + sctx->state[4] = H4; + sctx->state[5] = H5; + sctx->state[6] = H6; + sctx->state[7] = H7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha384_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = HP0; + sctx->state[1] = HP1; + sctx->state[2] = HP2; + sctx->state[3] = HP3; + sctx->state[4] = HP4; + sctx->state[5] = HP5; + sctx->state[6] = HP6; + sctx->state[7] = HP7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha512_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha512_ctx *sctx = ctx; + + unsigned int i, index, part_len; + + /* Compute number of bytes mod 128 */ + index = (unsigned int)((sctx->count[0] >> 3) & 0x7F); + + /* Update number of bits */ + if ((sctx->count[0] += (len << 3)) < (len << 3)) { + if ((sctx->count[1] += 1) < 1) + if ((sctx->count[2] += 1) < 1) + sctx->count[3]++; + sctx->count[1] += (len >> 29); + } + + part_len = 128 - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + sha512_transform(sctx->state, sctx->buf); + + for (i = part_len; i + 127 < len; i+=128) + sha512_transform(sctx->state, &data[i]); + + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&sctx->buf[index], &data[i], len - i); +} + +static void +sha512_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + + const static u8 padding[128] = { 0x80, }; + + u32 t; + u64 t2; + u8 bits[128]; + unsigned int index, pad_len; + int i, j; + + index = pad_len = t = i = j = 0; + t2 = 0; + + /* Save number of bits */ + t = sctx->count[0]; + bits[15] = t; t>>=8; + bits[14] = t; t>>=8; + bits[13] = t; t>>=8; + bits[12] = t; + t = sctx->count[1]; + bits[11] = t; t>>=8; + bits[10] = t; t>>=8; + bits[9 ] = t; t>>=8; + bits[8 ] = t; + t = sctx->count[2]; + bits[7 ] = t; t>>=8; + bits[6 ] = t; t>>=8; + bits[5 ] = t; t>>=8; + bits[4 ] = t; + t = sctx->count[3]; + bits[3 ] = t; t>>=8; + bits[2 ] = t; t>>=8; + bits[1 ] = t; t>>=8; + bits[0 ] = t; + + /* Pad out to 112 mod 128. */ + index = (sctx->count[0] >> 3) & 0x7f; + pad_len = (index < 112) ? (112 - index) : ((128+112) - index); + sha512_update(sctx, padding, pad_len); + + /* Append length (before padding) */ + sha512_update(sctx, bits, 16); + + /* Store state in digest */ + for (i = j = 0; i < 8; i++, j += 8) { + t2 = sctx->state[i]; + hash[j+7] = (char)t2 & 0xff; t2>>=8; + hash[j+6] = (char)t2 & 0xff; t2>>=8; + hash[j+5] = (char)t2 & 0xff; t2>>=8; + hash[j+4] = (char)t2 & 0xff; t2>>=8; + hash[j+3] = (char)t2 & 0xff; t2>>=8; + hash[j+2] = (char)t2 & 0xff; t2>>=8; + hash[j+1] = (char)t2 & 0xff; t2>>=8; + hash[j ] = (char)t2 & 0xff; + } + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(struct sha512_ctx)); +} + +static void sha384_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + u8 D[64]; + + sha512_final(sctx, D); + + memcpy(hash, D, 48); + memset(D, 0, 64); +} + +static struct crypto_alg sha512 = { + .cra_name = "sha512", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA512_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha512.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA512_DIGEST_SIZE, + .dia_init = sha512_init, + .dia_update = sha512_update, + .dia_final = sha512_final } + } +}; + +static struct crypto_alg sha384 = { + .cra_name = "sha384", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA384_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha384.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA384_DIGEST_SIZE, + .dia_init = sha384_init, + .dia_update = sha512_update, + .dia_final = sha384_final } + } +}; + +static int __init init(void) +{ + int ret = 0; + + if ((ret = crypto_register_alg(&sha384)) < 0) + goto out; + if ((ret = crypto_register_alg(&sha512)) < 0) + crypto_unregister_alg(&sha384); +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&sha384); + crypto_unregister_alg(&sha512); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/tcrypt.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,2418 @@ +/* + * Quick & dirty crypto testing module. + * + * This will only exist until we have a better testing mechanism + * (e.g. a char device). + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Jean-Francois Dive + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tcrypt.h" + +/* + * Need to kmalloc() memory for testing kmap(). + */ +#define TVMEMSIZE 4096 +#define XBUFSIZE 32768 + +/* + * Indexes into the xbuf to simulate cross-page access. + */ +#define IDX1 37 +#define IDX2 32400 +#define IDX3 1 +#define IDX4 8193 +#define IDX5 22222 +#define IDX6 17101 +#define IDX7 27333 +#define IDX8 3000 + +static int mode = 0; +static char *xbuf; +static char *tvmem; + +static char *check[] = { + "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", + "twofish", "serpent", "sha384", "sha512", "md4", "aes", "deflate", + NULL +}; + +static void +hexdump(unsigned char *buf, unsigned int len) +{ + while (len--) + printk("%02x", *buf++); + + printk("\n"); +} + +static void +test_md5(void) +{ + char *p; + unsigned int i; + struct scatterlist sg[2]; + char result[128]; + struct crypto_tfm *tfm; + struct md5_testvec *md5_tv; + unsigned int tsize; + + printk("\ntesting md5\n"); + + tsize = sizeof (md5_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, md5_tv_template, tsize); + md5_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("md5", 0); + if (tfm == NULL) { + printk("failed to load transform for md5\n"); + return; + } + + for (i = 0; i < MD5_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = md5_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(md5_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, md5_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting md5 across pages\n"); + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], "abcdefghijklm", 13); + memcpy(&xbuf[IDX2], "nopqrstuvwxyz", 13); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 13; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 13; + + memset(result, 0, sizeof (result)); + crypto_digest_digest(tfm, sg, 2, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + + printk("%s\n", + memcmp(result, md5_tv[4].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); + crypto_free_tfm(tfm); +} + +#ifdef CONFIG_CRYPTO_HMAC +static void +test_hmac_md5(void) +{ + char *p; + unsigned int i, klen; + struct scatterlist sg[2]; + char result[128]; + struct crypto_tfm *tfm; + struct hmac_md5_testvec *hmac_md5_tv; + unsigned int tsize; + + tfm = crypto_alloc_tfm("md5", 0); + if (tfm == NULL) { + printk("failed to load transform for md5\n"); + return; + } + + printk("\ntesting hmac_md5\n"); + + tsize = sizeof (hmac_md5_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, hmac_md5_tv_template, tsize); + hmac_md5_tv = (void *) tvmem; + + for (i = 0; i < HMAC_MD5_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = hmac_md5_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(hmac_md5_tv[i].plaintext); + + klen = strlen(hmac_md5_tv[i].key); + crypto_hmac(tfm, hmac_md5_tv[i].key, &klen, sg, 1, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, hmac_md5_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting hmac_md5 across pages\n"); + + memset(xbuf, 0, sizeof (xbuf)); + + memcpy(&xbuf[IDX1], "what do ya want ", 16); + memcpy(&xbuf[IDX2], "for nothing?", 12); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 16; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 12; + + memset(result, 0, sizeof (result)); + klen = strlen(hmac_md5_tv[7].key); + crypto_hmac(tfm, hmac_md5_tv[7].key, &klen, sg, 2, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + + printk("%s\n", + memcmp(result, hmac_md5_tv[7].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); +out: + crypto_free_tfm(tfm); +} + +static void +test_hmac_sha1(void) +{ + char *p; + unsigned int i, klen; + struct crypto_tfm *tfm; + struct hmac_sha1_testvec *hmac_sha1_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA1_DIGEST_SIZE]; + + tfm = crypto_alloc_tfm("sha1", 0); + if (tfm == NULL) { + printk("failed to load transform for sha1\n"); + return; + } + + printk("\ntesting hmac_sha1\n"); + + tsize = sizeof (hmac_sha1_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, hmac_sha1_tv_template, tsize); + hmac_sha1_tv = (void *) tvmem; + + for (i = 0; i < HMAC_SHA1_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = hmac_sha1_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(hmac_sha1_tv[i].plaintext); + + klen = strlen(hmac_sha1_tv[i].key); + + crypto_hmac(tfm, hmac_sha1_tv[i].key, &klen, sg, 1, result); + + hexdump(result, sizeof (result)); + printk("%s\n", + memcmp(result, hmac_sha1_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting hmac_sha1 across pages\n"); + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + memcpy(&xbuf[IDX1], "what do ya want ", 16); + memcpy(&xbuf[IDX2], "for nothing?", 12); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 16; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 12; + + memset(result, 0, sizeof (result)); + klen = strlen(hmac_sha1_tv[7].key); + crypto_hmac(tfm, hmac_sha1_tv[7].key, &klen, sg, 2, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + + printk("%s\n", + memcmp(result, hmac_sha1_tv[7].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); +out: + crypto_free_tfm(tfm); +} + +static void +test_hmac_sha256(void) +{ + char *p; + unsigned int i, klen; + struct crypto_tfm *tfm; + struct hmac_sha256_testvec *hmac_sha256_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA256_DIGEST_SIZE]; + + tfm = crypto_alloc_tfm("sha256", 0); + if (tfm == NULL) { + printk("failed to load transform for sha256\n"); + return; + } + + printk("\ntesting hmac_sha256\n"); + + tsize = sizeof (hmac_sha256_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, hmac_sha256_tv_template, tsize); + hmac_sha256_tv = (void *) tvmem; + + for (i = 0; i < HMAC_SHA256_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = hmac_sha256_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(hmac_sha256_tv[i].plaintext); + + klen = strlen(hmac_sha256_tv[i].key); + + hexdump(hmac_sha256_tv[i].key, strlen(hmac_sha256_tv[i].key)); + crypto_hmac(tfm, hmac_sha256_tv[i].key, &klen, sg, 1, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, hmac_sha256_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); + } + +out: + crypto_free_tfm(tfm); +} + +#endif /* CONFIG_CRYPTO_HMAC */ + +static void +test_md4(void) +{ + char *p; + unsigned int i; + struct scatterlist sg[1]; + char result[128]; + struct crypto_tfm *tfm; + struct md4_testvec *md4_tv; + unsigned int tsize; + + printk("\ntesting md4\n"); + + tsize = sizeof (md4_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, md4_tv_template, tsize); + md4_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("md4", 0); + if (tfm == NULL) { + printk("failed to load transform for md4\n"); + return; + } + + for (i = 0; i < MD4_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = md4_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(md4_tv[i].plaintext); + + crypto_digest_digest(tfm, sg, 1, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, md4_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + crypto_free_tfm(tfm); +} + +static void +test_sha1(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha1_testvec *sha1_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA1_DIGEST_SIZE]; + + printk("\ntesting sha1\n"); + + tsize = sizeof (sha1_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha1_tv_template, tsize); + sha1_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha1", 0); + if (tfm == NULL) { + printk("failed to load transform for sha1\n"); + return; + } + + for (i = 0; i < SHA1_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha1_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha1_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha1_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting sha1 across pages\n"); + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28); + memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 28; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 28; + + memset(result, 0, sizeof (result)); + crypto_digest_digest(tfm, sg, 2, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha1_tv[1].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); + crypto_free_tfm(tfm); +} + +static void +test_sha256(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha256_testvec *sha256_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA256_DIGEST_SIZE]; + + printk("\ntesting sha256\n"); + + tsize = sizeof (sha256_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha256_tv_template, tsize); + sha256_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha256", 0); + if (tfm == NULL) { + printk("failed to load transform for sha256\n"); + return; + } + + for (i = 0; i < SHA256_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha256_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha256_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha256_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting sha256 across pages\n"); + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28); + memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 28; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 28; + + memset(result, 0, sizeof (result)); + crypto_digest_digest(tfm, sg, 2, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha256_tv[1].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); + + crypto_free_tfm(tfm); +} + +static void +test_sha384(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha384_testvec *sha384_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA384_DIGEST_SIZE]; + + printk("\ntesting sha384\n"); + + tsize = sizeof (sha384_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha384_tv_template, tsize); + sha384_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha384", 0); + if (tfm == NULL) { + printk("failed to load transform for sha384\n"); + return; + } + + for (i = 0; i < SHA384_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha384_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha384_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha384_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + crypto_free_tfm(tfm); +} + +static void +test_sha512(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha512_testvec *sha512_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA512_DIGEST_SIZE]; + + printk("\ntesting sha512\n"); + + tsize = sizeof (sha512_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha512_tv_template, tsize); + sha512_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha512", 0); + if (tfm == NULL) { + printk("failed to load transform for sha512\n"); + return; + } + + for (i = 0; i < SHA512_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha512_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha512_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha512_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + crypto_free_tfm(tfm); +} + +void +test_des(void) +{ + unsigned int ret, i, len; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + char res[8]; + struct des_tv *des_tv; + struct scatterlist sg[8]; + + printk("\ntesting des encryption\n"); + + tsize = sizeof (des_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, des_enc_tv_template, tsize); + des_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("des", 0); + if (tfm == NULL) { + printk("failed to load transform for des (default ecb)\n"); + return; + } + + for (i = 0; i < DES_ENC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + key = des_tv[i].key; + tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!des_tv[i].fail) + goto out; + } + + len = des_tv[i].len; + + p = des_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + ret = crypto_cipher_encrypt(tfm, sg, sg, len); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + + } + + printk("\ntesting des ecb encryption across pages\n"); + + i = 5; + key = des_tv[i].key; + tfm->crt_flags = 0; + + hexdump(key, 8); + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8); + memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 8; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 8; + + ret = crypto_cipher_encrypt(tfm, sg, sg, 16); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass"); + + printk("\ntesting des ecb encryption chunking scenario A\n"); + + /* + * Scenario A: + * + * F1 F2 F3 + * [8 + 6] [2 + 8] [8] + * ^^^^^^ ^ + * a b c + * + * Chunking should begin at a, then end with b, and + * continue encrypting at an offset of 2 until c. + * + */ + i = 7; + + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + /* Frag 1: 8 + 6 */ + memcpy(&xbuf[IDX3], des_tv[i].plaintext, 14); + + /* Frag 2: 2 + 8 */ + memcpy(&xbuf[IDX4], des_tv[i].plaintext + 14, 10); + + /* Frag 3: 8 */ + memcpy(&xbuf[IDX5], des_tv[i].plaintext + 24, 8); + + p = &xbuf[IDX3]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 14; + + p = &xbuf[IDX4]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 10; + + p = &xbuf[IDX5]; + sg[2].page = virt_to_page(p); + sg[2].offset = ((long) p & ~PAGE_MASK); + sg[2].length = 8; + + ret = crypto_cipher_encrypt(tfm, sg, sg, 32); + + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 14); + printk("%s\n", memcmp(q, des_tv[i].result, 14) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 10); + printk("%s\n", memcmp(q, des_tv[i].result + 14, 10) ? "fail" : "pass"); + + printk("page 3\n"); + q = kmap(sg[2].page) + sg[2].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result + 24, 8) ? "fail" : "pass"); + + printk("\ntesting des ecb encryption chunking scenario B\n"); + + /* + * Scenario B: + * + * F1 F2 F3 F4 + * [2] [1] [3] [2 + 8 + 8] + */ + i = 7; + + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + /* Frag 1: 2 */ + memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2); + + /* Frag 2: 1 */ + memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 1); + + /* Frag 3: 3 */ + memcpy(&xbuf[IDX5], des_tv[i].plaintext + 3, 3); + + /* Frag 4: 2 + 8 + 8 */ + memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 18); + + p = &xbuf[IDX3]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 2; + + p = &xbuf[IDX4]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 1; + + p = &xbuf[IDX5]; + sg[2].page = virt_to_page(p); + sg[2].offset = ((long) p & ~PAGE_MASK); + sg[2].length = 3; + + p = &xbuf[IDX6]; + sg[3].page = virt_to_page(p); + sg[3].offset = ((long) p & ~PAGE_MASK); + sg[3].length = 18; + + ret = crypto_cipher_encrypt(tfm, sg, sg, 24); + + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 2); + printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 1); + printk("%s\n", memcmp(q, des_tv[i].result + 2, 1) ? "fail" : "pass"); + + printk("page 3\n"); + q = kmap(sg[2].page) + sg[2].offset; + hexdump(q, 3); + printk("%s\n", memcmp(q, des_tv[i].result + 3, 3) ? "fail" : "pass"); + + printk("page 4\n"); + q = kmap(sg[3].page) + sg[3].offset; + hexdump(q, 18); + printk("%s\n", memcmp(q, des_tv[i].result + 6, 18) ? "fail" : "pass"); + + printk("\ntesting des ecb encryption chunking scenario C\n"); + + /* + * Scenario B: + * + * F1 F2 F3 F4 F5 + * [2] [2] [2] [2] [8] + */ + i = 7; + + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + /* Frag 1: 2 */ + memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2); + + /* Frag 2: 2 */ + memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 2); + + /* Frag 3: 2 */ + memcpy(&xbuf[IDX5], des_tv[i].plaintext + 4, 2); + + /* Frag 4: 2 */ + memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 2); + + /* Frag 5: 8 */ + memcpy(&xbuf[IDX7], des_tv[i].plaintext + 8, 8); + + p = &xbuf[IDX3]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 2; + + p = &xbuf[IDX4]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 2; + + p = &xbuf[IDX5]; + sg[2].page = virt_to_page(p); + sg[2].offset = ((long) p & ~PAGE_MASK); + sg[2].length = 2; + + p = &xbuf[IDX6]; + sg[3].page = virt_to_page(p); + sg[3].offset = ((long) p & ~PAGE_MASK); + sg[3].length = 2; + + p = &xbuf[IDX7]; + sg[4].page = virt_to_page(p); + sg[4].offset = ((long) p & ~PAGE_MASK); + sg[4].length = 8; + + ret = crypto_cipher_encrypt(tfm, sg, sg, 16); + + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 2); + printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 2); + printk("%s\n", memcmp(q, des_tv[i].result + 2, 2) ? "fail" : "pass"); + + printk("page 3\n"); + q = kmap(sg[2].page) + sg[2].offset; + hexdump(q, 2); + printk("%s\n", memcmp(q, des_tv[i].result + 4, 2) ? "fail" : "pass"); + + printk("page 4\n"); + q = kmap(sg[3].page) + sg[3].offset; + hexdump(q, 2); + printk("%s\n", memcmp(q, des_tv[i].result + 6, 2) ? "fail" : "pass"); + + printk("page 5\n"); + q = kmap(sg[4].page) + sg[4].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass"); + + printk("\ntesting des ecb encryption chunking scenario D\n"); + + /* + * Scenario D, torture test, one byte per frag. + */ + i = 7; + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + xbuf[IDX1] = des_tv[i].plaintext[0]; + xbuf[IDX2] = des_tv[i].plaintext[1]; + xbuf[IDX3] = des_tv[i].plaintext[2]; + xbuf[IDX4] = des_tv[i].plaintext[3]; + xbuf[IDX5] = des_tv[i].plaintext[4]; + xbuf[IDX6] = des_tv[i].plaintext[5]; + xbuf[IDX7] = des_tv[i].plaintext[6]; + xbuf[IDX8] = des_tv[i].plaintext[7]; + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 1; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 1; + + p = &xbuf[IDX3]; + sg[2].page = virt_to_page(p); + sg[2].offset = ((long) p & ~PAGE_MASK); + sg[2].length = 1; + + p = &xbuf[IDX4]; + sg[3].page = virt_to_page(p); + sg[3].offset = ((long) p & ~PAGE_MASK); + sg[3].length = 1; + + p = &xbuf[IDX5]; + sg[4].page = virt_to_page(p); + sg[4].offset = ((long) p & ~PAGE_MASK); + sg[4].length = 1; + + p = &xbuf[IDX6]; + sg[5].page = virt_to_page(p); + sg[5].offset = ((long) p & ~PAGE_MASK); + sg[5].length = 1; + + p = &xbuf[IDX7]; + sg[6].page = virt_to_page(p); + sg[6].offset = ((long) p & ~PAGE_MASK); + sg[6].length = 1; + + p = &xbuf[IDX8]; + sg[7].page = virt_to_page(p); + sg[7].offset = ((long) p & ~PAGE_MASK); + sg[7].length = 1; + + ret = crypto_cipher_encrypt(tfm, sg, sg, 8); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + for (i = 0; i < 8; i++) + res[i] = *(char *) (kmap(sg[i].page) + sg[i].offset); + + hexdump(res, 8); + printk("%s\n", memcmp(res, des_tv[7].result, 8) ? "fail" : "pass"); + + printk("\ntesting des decryption\n"); + + tsize = sizeof (des_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + memcpy(tvmem, des_dec_tv_template, tsize); + des_tv = (void *) tvmem; + + for (i = 0; i < DES_DEC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + key = des_tv[i].key; + + tfm->crt_flags = 0; + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + len = des_tv[i].len; + + p = des_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("des_decrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + + } + + printk("\ntesting des ecb decryption across pages\n"); + + i = 6; + + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8); + memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 8; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 8; + + ret = crypto_cipher_decrypt(tfm, sg, sg, 16); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 8); + printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass"); + + /* + * Scenario E: + * + * F1 F2 F3 + * [3] [5 + 7] [1] + * + */ + printk("\ntesting des ecb decryption chunking scenario E\n"); + i = 2; + + key = des_tv[i].key; + tfm->crt_flags = 0; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + memcpy(&xbuf[IDX1], des_tv[i].plaintext, 3); + memcpy(&xbuf[IDX2], des_tv[i].plaintext + 3, 12); + memcpy(&xbuf[IDX3], des_tv[i].plaintext + 15, 1); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 3; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 12; + + p = &xbuf[IDX3]; + sg[2].page = virt_to_page(p); + sg[2].offset = ((long) p & ~PAGE_MASK); + sg[2].length = 1; + + ret = crypto_cipher_decrypt(tfm, sg, sg, 16); + + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 3); + printk("%s\n", memcmp(q, des_tv[i].result, 3) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 12); + printk("%s\n", memcmp(q, des_tv[i].result + 3, 12) ? "fail" : "pass"); + + printk("page 3\n"); + q = kmap(sg[2].page) + sg[2].offset; + hexdump(q, 1); + printk("%s\n", memcmp(q, des_tv[i].result + 15, 1) ? "fail" : "pass"); + + crypto_free_tfm(tfm); + + tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC); + if (tfm == NULL) { + printk("failed to load transform for des cbc\n"); + return; + } + + printk("\ntesting des cbc encryption\n"); + + tsize = sizeof (des_cbc_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + memcpy(tvmem, des_cbc_enc_tv_template, tsize); + des_tv = (void *) tvmem; + + crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_get_iv(tfm, res, crypto_tfm_alg_ivsize(tfm)); + + if (memcmp(res, des_tv[i].iv, sizeof(res))) { + printk("crypto_cipher_[set|get]_iv() failed\n"); + goto out; + } + + for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + key = des_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + len = des_tv[i].len; + p = des_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + + crypto_cipher_set_iv(tfm, des_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_encrypt(tfm, sg, sg, len); + if (ret) { + printk("des_cbc_encrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + } + + crypto_free_tfm(tfm); + + /* + * Scenario F: + * + * F1 F2 + * [8 + 5] [3 + 8] + * + */ + printk("\ntesting des cbc encryption chunking scenario F\n"); + i = 4; + + tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC); + if (tfm == NULL) { + printk("failed to load transform for CRYPTO_ALG_DES_CCB\n"); + return; + } + + tfm->crt_flags = 0; + key = des_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + + memcpy(&xbuf[IDX1], des_tv[i].plaintext, 13); + memcpy(&xbuf[IDX2], des_tv[i].plaintext + 13, 11); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 13; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 11; + + crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_encrypt(tfm, sg, sg, 24); + if (ret) { + printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 13); + printk("%s\n", memcmp(q, des_tv[i].result, 13) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 11); + printk("%s\n", memcmp(q, des_tv[i].result + 13, 11) ? "fail" : "pass"); + + tsize = sizeof (des_cbc_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + memcpy(tvmem, des_cbc_dec_tv_template, tsize); + des_tv = (void *) tvmem; + + printk("\ntesting des cbc decryption\n"); + + for (i = 0; i < DES_CBC_DEC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + tfm->crt_flags = 0; + key = des_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + len = des_tv[i].len; + p = des_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + + crypto_cipher_set_iv(tfm, des_tv[i].iv, + crypto_tfm_alg_blocksize(tfm)); + + ret = crypto_cipher_decrypt(tfm, sg, sg, len); + if (ret) { + printk("des_cbc_decrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + hexdump(tfm->crt_cipher.cit_iv, 8); + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + } + + /* + * Scenario G: + * + * F1 F2 + * [4] [4] + * + */ + printk("\ntesting des cbc decryption chunking scenario G\n"); + i = 3; + + tfm->crt_flags = 0; + key = des_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, 8); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + /* setup the dummy buffer first */ + memset(xbuf, 0, sizeof (xbuf)); + memcpy(&xbuf[IDX1], des_tv[i].plaintext, 4); + memcpy(&xbuf[IDX2], des_tv[i].plaintext + 4, 4); + + p = &xbuf[IDX1]; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = 4; + + p = &xbuf[IDX2]; + sg[1].page = virt_to_page(p); + sg[1].offset = ((long) p & ~PAGE_MASK); + sg[1].length = 4; + + crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_decrypt(tfm, sg, sg, 8); + if (ret) { + printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + printk("page 1\n"); + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, 4); + printk("%s\n", memcmp(q, des_tv[i].result, 4) ? "fail" : "pass"); + + printk("page 2\n"); + q = kmap(sg[1].page) + sg[1].offset; + hexdump(q, 4); + printk("%s\n", memcmp(q, des_tv[i].result + 4, 4) ? "fail" : "pass"); + + out: + crypto_free_tfm(tfm); +} + +void +test_des3_ede(void) +{ + unsigned int ret, i, len; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + /*char res[8]; */ + struct des_tv *des_tv; + struct scatterlist sg[8]; + + printk("\ntesting des3 ede encryption\n"); + + tsize = sizeof (des3_ede_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, des3_ede_enc_tv_template, tsize); + des_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("des3_ede", CRYPTO_TFM_MODE_ECB); + if (tfm == NULL) { + printk("failed to load transform for 3des ecb\n"); + return; + } + + for (i = 0; i < DES3_EDE_ENC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + key = des_tv[i].key; + ret = crypto_cipher_setkey(tfm, key, 24); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!des_tv[i].fail) + goto out; + } + + len = des_tv[i].len; + + p = des_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + ret = crypto_cipher_encrypt(tfm, sg, sg, len); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + } + + printk("\ntesting des3 ede decryption\n"); + + tsize = sizeof (des3_ede_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, des3_ede_dec_tv_template, tsize); + des_tv = (void *) tvmem; + + for (i = 0; i < DES3_EDE_DEC_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + + key = des_tv[i].key; + ret = crypto_cipher_setkey(tfm, key, 24); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!des_tv[i].fail) + goto out; + } + + len = des_tv[i].len; + + p = des_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = len; + ret = crypto_cipher_decrypt(tfm, sg, sg, len); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, len); + + printk("%s\n", + memcmp(q, des_tv[i].result, len) ? "fail" : "pass"); + } + + out: + crypto_free_tfm(tfm); +} + +void +test_blowfish(void) +{ + unsigned int ret, i; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + struct bf_tv *bf_tv; + struct scatterlist sg[1]; + + printk("\ntesting blowfish encryption\n"); + + tsize = sizeof (bf_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, bf_enc_tv_template, tsize); + bf_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("blowfish", 0); + if (tfm == NULL) { + printk("failed to load transform for blowfish (default ecb)\n"); + return; + } + + for (i = 0; i < BF_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, bf_tv[i].keylen * 8); + key = bf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!bf_tv[i].fail) + goto out; + } + + p = bf_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = bf_tv[i].plen; + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, bf_tv[i].rlen); + + printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ? + "fail" : "pass"); + } + + printk("\ntesting blowfish decryption\n"); + + tsize = sizeof (bf_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, bf_dec_tv_template, tsize); + bf_tv = (void *) tvmem; + + for (i = 0; i < BF_DEC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, bf_tv[i].keylen * 8); + key = bf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!bf_tv[i].fail) + goto out; + } + + p = bf_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = bf_tv[i].plen; + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, bf_tv[i].rlen); + + printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ? + "fail" : "pass"); + } + + crypto_free_tfm(tfm); + + tfm = crypto_alloc_tfm("blowfish", CRYPTO_TFM_MODE_CBC); + if (tfm == NULL) { + printk("failed to load transform for blowfish cbc\n"); + return; + } + + printk("\ntesting blowfish cbc encryption\n"); + + tsize = sizeof (bf_cbc_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + memcpy(tvmem, bf_cbc_enc_tv_template, tsize); + bf_tv = (void *) tvmem; + + for (i = 0; i < BF_CBC_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, bf_tv[i].keylen * 8); + + key = bf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + p = bf_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = bf_tv[i].plen; + + crypto_cipher_set_iv(tfm, bf_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("blowfish_cbc_encrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, bf_tv[i].rlen); + + printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) + ? "fail" : "pass"); + } + + printk("\ntesting blowfish cbc decryption\n"); + + tsize = sizeof (bf_cbc_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + memcpy(tvmem, bf_cbc_dec_tv_template, tsize); + bf_tv = (void *) tvmem; + + for (i = 0; i < BF_CBC_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, bf_tv[i].keylen * 8); + key = bf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + p = bf_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = bf_tv[i].plen; + + crypto_cipher_set_iv(tfm, bf_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("blowfish_cbc_decrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, bf_tv[i].rlen); + + printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) + ? "fail" : "pass"); + } + +out: + crypto_free_tfm(tfm); +} + + +void +test_twofish(void) +{ + unsigned int ret, i; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + struct tf_tv *tf_tv; + struct scatterlist sg[1]; + + printk("\ntesting twofish encryption\n"); + + tsize = sizeof (tf_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, tf_enc_tv_template, tsize); + tf_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("twofish", 0); + if (tfm == NULL) { + printk("failed to load transform for blowfish (default ecb)\n"); + return; + } + + for (i = 0; i < TF_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, tf_tv[i].keylen * 8); + key = tf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!tf_tv[i].fail) + goto out; + } + + p = tf_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = tf_tv[i].plen; + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, tf_tv[i].rlen); + + printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ? + "fail" : "pass"); + } + + printk("\ntesting twofish decryption\n"); + + tsize = sizeof (tf_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, tf_dec_tv_template, tsize); + tf_tv = (void *) tvmem; + + for (i = 0; i < TF_DEC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, tf_tv[i].keylen * 8); + key = tf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!tf_tv[i].fail) + goto out; + } + + p = tf_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = tf_tv[i].plen; + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, tf_tv[i].rlen); + + printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ? + "fail" : "pass"); + } + + crypto_free_tfm(tfm); + + tfm = crypto_alloc_tfm("twofish", CRYPTO_TFM_MODE_CBC); + if (tfm == NULL) { + printk("failed to load transform for twofish cbc\n"); + return; + } + + printk("\ntesting twofish cbc encryption\n"); + + tsize = sizeof (tf_cbc_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + memcpy(tvmem, tf_cbc_enc_tv_template, tsize); + tf_tv = (void *) tvmem; + + for (i = 0; i < TF_CBC_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, tf_tv[i].keylen * 8); + + key = tf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + p = tf_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = tf_tv[i].plen; + + crypto_cipher_set_iv(tfm, tf_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("blowfish_cbc_encrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, tf_tv[i].rlen); + + printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) + ? "fail" : "pass"); + } + + printk("\ntesting twofish cbc decryption\n"); + + tsize = sizeof (tf_cbc_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + memcpy(tvmem, tf_cbc_dec_tv_template, tsize); + tf_tv = (void *) tvmem; + + for (i = 0; i < TF_CBC_DEC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, tf_tv[i].keylen * 8); + + key = tf_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + p = tf_tv[i].plaintext; + + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = tf_tv[i].plen; + + crypto_cipher_set_iv(tfm, tf_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("blowfish_cbc_decrypt() failed flags=%x\n", + tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, tf_tv[i].rlen); + + printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) + ? "fail" : "pass"); + } + +out: + crypto_free_tfm(tfm); +} + +void +test_serpent(void) +{ + unsigned int ret, i, tsize; + u8 *p, *q, *key; + struct crypto_tfm *tfm; + struct serpent_tv *serp_tv; + struct scatterlist sg[1]; + + printk("\ntesting serpent encryption\n"); + + tfm = crypto_alloc_tfm("serpent", 0); + if (tfm == NULL) { + printk("failed to load transform for serpent (default ecb)\n"); + return; + } + + tsize = sizeof (serpent_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, serpent_enc_tv_template, tsize); + serp_tv = (void *) tvmem; + for (i = 0; i < SERPENT_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", i + 1, serp_tv[i].keylen * 8); + key = serp_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, serp_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!serp_tv[i].fail) + goto out; + } + + p = serp_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = sizeof(serp_tv[i].plaintext); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, sizeof(serp_tv[i].result)); + + printk("%s\n", memcmp(q, serp_tv[i].result, + sizeof(serp_tv[i].result)) ? "fail" : "pass"); + } + + printk("\ntesting serpent decryption\n"); + + tsize = sizeof (serpent_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, serpent_dec_tv_template, tsize); + serp_tv = (void *) tvmem; + for (i = 0; i < SERPENT_DEC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", i + 1, serp_tv[i].keylen * 8); + key = serp_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, serp_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!serp_tv[i].fail) + goto out; + } + + p = serp_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = sizeof(serp_tv[i].plaintext); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, sizeof(serp_tv[i].result)); + + printk("%s\n", memcmp(q, serp_tv[i].result, + sizeof(serp_tv[i].result)) ? "fail" : "pass"); + } + +out: + crypto_free_tfm(tfm); +} + +void +test_aes(void) +{ + unsigned int ret, i; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + struct aes_tv *aes_tv; + struct scatterlist sg[1]; + + printk("\ntesting aes encryption\n"); + + tsize = sizeof (aes_enc_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, aes_enc_tv_template, tsize); + aes_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("aes", 0); + if (tfm == NULL) { + printk("failed to load transform for aes (default ecb)\n"); + return; + } + + for (i = 0; i < AES_ENC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, aes_tv[i].keylen * 8); + key = aes_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!aes_tv[i].fail) + goto out; + } + + p = aes_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = aes_tv[i].plen; + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("encrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, aes_tv[i].rlen); + + printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ? + "fail" : "pass"); + } + + printk("\ntesting aes decryption\n"); + + tsize = sizeof (aes_dec_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, aes_dec_tv_template, tsize); + aes_tv = (void *) tvmem; + + for (i = 0; i < AES_DEC_TEST_VECTORS; i++) { + printk("test %u (%d bit key):\n", + i + 1, aes_tv[i].keylen * 8); + key = aes_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!aes_tv[i].fail) + goto out; + } + + p = aes_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = aes_tv[i].plen; + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); + if (ret) { + printk("decrypt() failed flags=%x\n", tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, aes_tv[i].rlen); + + printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ? + "fail" : "pass"); + } + +out: + crypto_free_tfm(tfm); +} + +static void +test_deflate(void) +{ + unsigned int i; + char result[COMP_BUF_SIZE]; + struct crypto_tfm *tfm; + struct comp_testvec *tv; + unsigned int tsize; + + printk("\ntesting deflate compression\n"); + + tsize = sizeof (deflate_comp_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, deflate_comp_tv_template, tsize); + tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("deflate", 0); + if (tfm == NULL) { + printk("failed to load transform for deflate\n"); + return; + } + + for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) { + int ilen, ret, dlen = COMP_BUF_SIZE; + + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + ilen = tv[i].inlen; + ret = crypto_comp_compress(tfm, tv[i].input, + ilen, result, &dlen); + if (ret) { + printk("fail: ret=%d\n", ret); + continue; + } + hexdump(result, dlen); + printk("%s (ratio %d:%d)\n", + memcmp(result, tv[i].output, dlen) ? "fail" : "pass", + ilen, dlen); + } + + printk("\ntesting deflate decompression\n"); + + tsize = sizeof (deflate_decomp_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, deflate_decomp_tv_template, tsize); + tv = (void *) tvmem; + + for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) { + int ilen, ret, dlen = COMP_BUF_SIZE; + + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + ilen = tv[i].inlen; + ret = crypto_comp_decompress(tfm, tv[i].input, + ilen, result, &dlen); + if (ret) { + printk("fail: ret=%d\n", ret); + continue; + } + hexdump(result, dlen); + printk("%s (ratio %d:%d)\n", + memcmp(result, tv[i].output, dlen) ? "fail" : "pass", + ilen, dlen); + } +out: + crypto_free_tfm(tfm); +} + +static void +test_available(void) +{ + char **name = check; + + while (*name) { + printk("alg %s ", *name); + printk((crypto_alg_available(*name, 0)) ? + "found\n" : "not found\n"); + name++; + } +} + +static void +do_test(void) +{ + switch (mode) { + + case 0: + test_md5(); + test_sha1(); + test_des(); + test_des3_ede(); + test_md4(); + test_sha256(); + test_blowfish(); + test_twofish(); + test_serpent(); + test_aes(); + test_sha384(); + test_sha512(); + test_deflate(); +#ifdef CONFIG_CRYPTO_HMAC + test_hmac_md5(); + test_hmac_sha1(); + test_hmac_sha256(); +#endif + break; + + case 1: + test_md5(); + break; + + case 2: + test_sha1(); + break; + + case 3: + test_des(); + break; + + case 4: + test_des3_ede(); + break; + + case 5: + test_md4(); + break; + + case 6: + test_sha256(); + break; + + case 7: + test_blowfish(); + break; + + case 8: + test_twofish(); + break; + + case 9: + test_serpent(); + break; + + case 10: + test_aes(); + break; + + case 11: + test_sha384(); + break; + + case 12: + test_sha512(); + break; + + case 13: + test_deflate(); + break; + +#ifdef CONFIG_CRYPTO_HMAC + case 100: + test_hmac_md5(); + break; + + case 101: + test_hmac_sha1(); + break; + + case 102: + test_hmac_sha256(); + break; + +#endif + + case 1000: + test_available(); + break; + + default: + /* useful for debugging */ + printk("not testing anything\n"); + break; + } +} + +static int __init +init(void) +{ + tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); + if (tvmem == NULL) + return -ENOMEM; + + xbuf = kmalloc(XBUFSIZE, GFP_KERNEL); + if (xbuf == NULL) { + kfree(tvmem); + return -ENOMEM; + } + + do_test(); + + kfree(xbuf); + kfree(tvmem); + return 0; +} + +module_init(init); + +MODULE_PARM(mode, "i"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Quick & dirty crypto testing module"); +MODULE_AUTHOR("James Morris "); diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/tcrypt.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,1785 @@ +/* + * Quick & dirty crypto testing module. + * + * This will only exist until we have a better testing mechanism + * (e.g. a char device). + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Jean-Francois Dive + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_TCRYPT_H +#define _CRYPTO_TCRYPT_H + +#define MD5_DIGEST_SIZE 16 +#define MD4_DIGEST_SIZE 16 +#define SHA1_DIGEST_SIZE 20 +#define SHA256_DIGEST_SIZE 32 +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 + +/* + * MD4 test vectors from RFC1320 + */ +#define MD4_TEST_VECTORS 7 + +struct md4_testvec { + char plaintext[128]; + char digest[MD4_DIGEST_SIZE]; +} md4_tv_template[] = { + { "", + { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 } + }, + + { "a", + { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 } + }, + + { "abc", + { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d } + }, + + { "message digest", + { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b } + }, + + { "abcdefghijklmnopqrstuvwxyz", + { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 } + }, + + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 } + }, + + { "123456789012345678901234567890123456789012345678901234567890123" + "45678901234567890", + { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 } + }, +}; + +/* + * MD5 test vectors from RFC1321 + */ +#define MD5_TEST_VECTORS 7 + +struct md5_testvec { + char plaintext[128]; + char digest[MD5_DIGEST_SIZE]; +} md5_tv_template[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + + { "a", + { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } } +}; + +#ifdef CONFIG_CRYPTO_HMAC +/* + * HMAC-MD5 test vectors from RFC2202 + * (These need to be fixed to not use strlen). + */ +#define HMAC_MD5_TEST_VECTORS 7 + +struct hmac_md5_testvec { + char key[128]; + char plaintext[128]; + char digest[MD5_DIGEST_SIZE]; +}; + +struct hmac_md5_testvec hmac_md5_tv_template[] = +{ + + { + { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00}, + + "Hi There", + + { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d } + }, + + { + { 'J', 'e', 'f', 'e', 0 }, + + "what do ya want for nothing?", + + { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 }, + + { 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, + 0x00 }, + + { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 } + }, + + { + { 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, 0x00 }, + + { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0x00 }, + + { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 } + }, + + { + { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 }, + + "Test With Truncation", + + { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00 }, + + "Test Using Larger Than Block-Size Key - Hash Key First", + + { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00 }, + + "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + + { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e } + }, + + /* cross page test, need to retain key */ + + { + { 'J', 'e', 'f', 'e', 0 }, + + "what do ya want for nothing?", + + { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 } + }, + +}; + + +/* + * HMAC-SHA1 test vectors from RFC2202 + */ + +#define HMAC_SHA1_TEST_VECTORS 7 + +struct hmac_sha1_testvec { + char key[128]; + char plaintext[128]; + char digest[SHA1_DIGEST_SIZE]; +} hmac_sha1_tv_template[] = { + + { + { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x00}, + + "Hi There", + + { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb ,0x37, 0x8c, 0x8e, 0xf1, + 0x46, 0xbe, 0x00 } + }, + + { + { 'J', 'e', 'f', 'e', 0 }, + + "what do ya want for nothing?", + + { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, + 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 } + + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00}, + + + { 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, + 0x00 }, + + { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, + 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 } + + }, + + { + { 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, 0x00 }, + + { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0x00 }, + + { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, + 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda } + + }, + + { + { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x00 }, + + "Test With Truncation", + + { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 } + + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00 }, + + "Test Using Larger Than Block-Size Key - Hash Key First", + + { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, + 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 } + + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00 }, + + "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + + { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, + 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 } + }, + + /* cross page test */ + { + { 'J', 'e', 'f', 'e', 0 }, + + "what do ya want for nothing?", + + { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, + 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 } + + }, + +}; + +/* + * HMAC-SHA256 test vectors from + * draft-ietf-ipsec-ciph-sha-256-01.txt + */ +#define HMAC_SHA256_TEST_VECTORS 10 + +struct hmac_sha256_testvec { + char key[128]; + char plaintext[128]; + char digest[SHA256_DIGEST_SIZE]; +} hmac_sha256_tv_template[] = { + + { + { 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, 0x20, 0x00 }, + + + { "abc" }, + + { 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a, + 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a, + 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66, + 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 }, + + }, + + { + { 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, 0x20, 0x00 }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + + { 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08, + 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae, + 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49, + 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 } + }, + + { + { 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, 0x20, 0x00 }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + + { 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34, + 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab, + 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5, + 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 } + }, + + { + { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00 }, + + { "Hi There" }, + + { 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6, + 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5, + 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c, + 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 } + }, + + { + { "Jefe" }, + + { "what do ya want for nothing?" }, + + { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 }, + + { 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, 0x00 }, + + { 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea, + 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62, + 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc, + 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 } + }, + + { + { 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, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x00 }, + + { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0x00 }, + + { 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74, + 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55, + 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85, + 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 } + }, + + { + { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 }, + + { "Test With Truncation" }, + + { 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b, + 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17, + 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27, + 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 }, + + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + + { 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09, + 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb, + 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e, + 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f } + }, + + { + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 }, + + { "Test Using Larger Than Block-Size Key and Larger Than " + "One Block-Size Data" }, + + { 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3, + 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8, + 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc, + 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 } + }, +}; + + +#endif /* CONFIG_CRYPTO_HMAC */ + +/* + * SHA1 test vectors from from FIPS PUB 180-1 + */ +#define SHA1_TEST_VECTORS 2 + +struct sha1_testvec { + char plaintext[128]; + char digest[SHA1_DIGEST_SIZE]; +} sha1_tv_template[] = { + { "abc", + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C ,0x9C, 0xD0, 0xD8, 0x9D } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E ,0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 } + } +}; + +/* + * SHA256 test vectors from from NIST + */ +#define SHA256_TEST_VECTORS 2 + +struct sha256_testvec { + char plaintext[128]; + char digest[SHA256_DIGEST_SIZE]; +} sha256_tv_template[] = { + { "abc", + { 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 } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 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 } + }, +}; + +/* + * SHA384 test vectors from from NIST and kerneli + */ +#define SHA384_TEST_VECTORS 4 + +struct sha384_testvec { + char plaintext[128]; + char digest[SHA384_DIGEST_SIZE]; +} sha384_tv_template[] = { + + { "abc", + { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, + 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39, + 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab, + 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, + 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, + 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b } + }, + + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } + }, + + { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb, + 0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a, + 0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc, + 0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a, + 0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a, + 0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 } + }, +}; + +/* + * SHA512 test vectors from from NIST and kerneli + */ +#define SHA512_TEST_VECTORS 4 + +struct sha512_testvec { + char plaintext[128]; + char digest[SHA512_DIGEST_SIZE]; +} sha512_tv_template[] = { + + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, + 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16, + 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8, + 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, + 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, + 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0, + 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03, + 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 } + }, + + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + + { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11, + 0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d, + 0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c, + 0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d, + 0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67, + 0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe, + 0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8, + 0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 + } + }, +}; + +/* + * DES test vectors. + */ +#define DES_ENC_TEST_VECTORS 5 +#define DES_DEC_TEST_VECTORS 2 +#define DES_CBC_ENC_TEST_VECTORS 4 +#define DES_CBC_DEC_TEST_VECTORS 3 +#define DES3_EDE_ENC_TEST_VECTORS 3 +#define DES3_EDE_DEC_TEST_VECTORS 3 + +struct des_tv { + unsigned int len; + int fail; + char key[24]; + char iv[8]; + char plaintext[128]; + char result[128]; +}; + +struct des_tv des_enc_tv_template[] = { + + /* From Applied Cryptography */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d } + }, + + /* Same key, different plaintext block */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0 }, + { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b } + }, + + /* Sbox test from NBS */ + { + 8, 0, + + { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 }, + { 0 }, + { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 }, + { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B } + }, + + /* Three blocks */ + { + 24, 0, + + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + + { 0 }, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef }, + + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b, + 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 }, + }, + + /* Weak key */ + { + 8, 1, + + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d } + }, + + /* Two blocks -- for testing encryption across pages */ + { + 16, 0, + + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + + { 0 }, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b } + }, + + /* Two blocks -- for testing decryption across pages */ + { + 16, 0, + + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + + { 0 }, + + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + }, + + /* Four blocks -- for testing encryption with chunking */ + { + 24, 0, + + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + + { 0 }, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b, + 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + }, + +}; + +struct des_tv des_dec_tv_template[] = { + + /* From Applied Cryptography */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0 }, + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + }, + + /* Sbox test from NBS */ + { + 8, 0, + + { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 }, + { 0 }, + { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B }, + { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 } + }, + + /* Two blocks, for chunking test */ + { + 16, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0 }, + + { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B }, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 } + }, + +}; + +struct des_tv des_cbc_enc_tv_template[] = { + /* From OpenSSL */ + { + 24, 0, + + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + + { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, + 0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 }, + + { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, + 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, + 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68, + 0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 } + }, + + /* FIPS Pub 81 */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }, + { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }, + { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + + }, + + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + }, + + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + }, + + /* Copy of openssl vector for chunk testing */ + + /* From OpenSSL */ + { + 24, 0, + + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + + { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, + 0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 }, + + { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, + 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, + 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68, + 0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 } + }, + + +}; + +struct des_tv des_cbc_dec_tv_template[] = { + + /* FIPS Pub 81 */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }, + { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }, + }, + + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + }, + + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + }, + + /* Copy of above, for chunk testing */ + + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + }, +}; + +/* + * We really need some more test vectors, especially for DES3 CBC. + */ +struct des_tv des3_ede_enc_tv_template[] = { + + /* These are from openssl */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, + + { 0 }, + + { 0x73, 0x6F, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x61 }, + + { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 }, + }, + + { + 8, 0, + + { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, + 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, + 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, + + { 0 }, + + { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, + + { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } + }, + + + { + 8, 0, + + { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, + 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, + 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, + + { 0 }, + + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + + { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } + }, +}; + +struct des_tv des3_ede_dec_tv_template[] = { + + /* These are from openssl */ + { + 8, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, + + { 0 }, + + + { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 }, + + { 0x73, 0x6F, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x61 }, + }, + + { + 8, 0, + + { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, + 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, + 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, + + { 0 }, + + { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 }, + + { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, + + }, + + + { + 8, 0, + + { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, + 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, + 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, + + { 0 }, + + { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b }, + + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + }, +}; + +/* + * Blowfish test vectors. + */ +#define BF_ENC_TEST_VECTORS 6 +#define BF_DEC_TEST_VECTORS 6 +#define BF_CBC_ENC_TEST_VECTORS 1 +#define BF_CBC_DEC_TEST_VECTORS 1 + +struct bf_tv { + unsigned int keylen; + unsigned int plen; + unsigned int rlen; + int fail; + char key[56]; + char iv[8]; + char plaintext[32]; + char result[32]; +}; + +struct bf_tv bf_enc_tv_template[] = { + + /* DES test vectors from OpenSSL */ + { + 8, 8, 8, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + { 0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78 }, + }, + + { + 8, 8, 8, 0, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, }, + { 0 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE }, + }, + + { + 8, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, }, + { 0 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0xE8, 0x7A, 0x24, 0x4E, 0x2C, 0xC8, 0x5E, 0x82 } + }, + + /* Vary the keylength... */ + + { + 16, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F }, + { 0 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x93, 0x14, 0x28, 0x87, 0xEE, 0x3B, 0xE1, 0x5C } + }, + + { + 21, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, + 0x00, 0x11, 0x22, 0x33, 0x44 }, + { 0 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0xE6, 0xF5, 0x1E, 0xD7, 0x9B, 0x9D, 0xB2, 0x1F } + }, + + /* Generated with bf488 */ + { + 56, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F, + 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76, + 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 } + } + +}; + +struct bf_tv bf_dec_tv_template[] = { + + /* DES test vectors from OpenSSL */ + { + 8, 8, 8, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + { 0 }, + { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + + { + 8, 8, 8, 0, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, }, + { 0 }, + { 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF } + }, + + { + 8, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, }, + { 0 }, + { 0xE8, 0x7A, 0x24, 0x4E, 0x2C, 0xC8, 0x5E, 0x82 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } + }, + + /* Vary the keylength... */ + + { + 16, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F }, + { 0 }, + { 0x93, 0x14, 0x28, 0x87, 0xEE, 0x3B, 0xE1, 0x5C }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } + }, + + { + 21, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, + 0x00, 0x11, 0x22, 0x33, 0x44 }, + { 0 }, + { 0xE6, 0xF5, 0x1E, 0xD7, 0x9B, 0x9D, 0xB2, 0x1F }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } + }, + + /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */ + { + 56, 8, 8, 0, + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F, + 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76, + 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0 }, + { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } + } +}; + +struct bf_tv bf_cbc_enc_tv_template[] = { + + /* From OpenSSL */ + { + 16, 32, 32, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }, + + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + + { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, + 0x66, 0x6F, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 }, + + { 0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6, + 0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93, + 0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9, + 0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC } + }, +}; + +struct bf_tv bf_cbc_dec_tv_template[] = { + + /* From OpenSSL */ + { + 16, 32, 32, 0, + + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }, + + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + + { 0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6, + 0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93, + 0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9, + 0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC }, + + { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, + 0x66, 0x6F, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +/* + * Twofish test vectors. + */ +#define TF_ENC_TEST_VECTORS 3 +#define TF_DEC_TEST_VECTORS 3 +#define TF_CBC_ENC_TEST_VECTORS 4 +#define TF_CBC_DEC_TEST_VECTORS 4 + +struct tf_tv { + unsigned int keylen; + unsigned int plen; + unsigned int rlen; + int fail; + char key[32]; + char iv[16]; + char plaintext[48]; + char result[48]; +}; + +struct tf_tv tf_enc_tv_template[] = { + { + 16, 16, 16, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A } + }, + { + 24, 16, 16, 0, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, + 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 } + }, + { + 32, 16, 16, 0, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, + { 0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, + 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 } + }, +}; + +struct tf_tv tf_dec_tv_template[] = { + { + 16, 16, 16, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0 }, + { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + { + 24, 16, 16, 0, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0 }, + { 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, + 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + { + 32, 16, 16, 0, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, + { 0 }, + { 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, + 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, +}; + +struct tf_tv tf_cbc_enc_tv_template[] = { + /* Generated with Nettle */ + { + 16, 16, 16, 0, + + { 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 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + }, + + { + 16, 16, 16, 0, + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + }, + + { + 16, 16, 16, 0, + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + }, + + { + 16, 48, 48, 0, + + { 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, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a, + 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19, + 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + }, +}; + +struct tf_tv tf_cbc_dec_tv_template[] = { + /* Reverse of the first four above */ + { + 16, 16, 16, 0, + + { 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 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + + { + 16, 16, 16, 0, + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + + { + 16, 16, 16, 0, + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + + { + 16, 48, 48, 0, + + { 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 }, + { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a, + 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19, + 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + { 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 }, + }, +}; + +/* + * Serpent test vectors. These are backwards because Serpent writes + * octect sequences in right-to-left mode. + */ +#define SERPENT_ENC_TEST_VECTORS 4 +#define SERPENT_DEC_TEST_VECTORS 4 + +struct serpent_tv { + unsigned int keylen, fail; + u8 key[32], plaintext[16], result[16]; +}; + +struct serpent_tv serpent_enc_tv_template[] = +{ + { + 0, 0, + { 0 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47, + 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 } + }, + { + 16, 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c, + 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d } + }, + { + 32, 0, + { 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 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, + 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c } + }, + { + 16, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c, + 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49} + } +}; + +struct serpent_tv serpent_dec_tv_template[] = +{ + { + 0, 0, + { 0 }, + { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47, + 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + }, + { + 16, 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c, + 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + 32, 0, + { 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 }, + + { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, + 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + 16, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c, + 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + } +}; + +/* + * AES test vectors. + */ +#define AES_ENC_TEST_VECTORS 3 +#define AES_DEC_TEST_VECTORS 3 + +struct aes_tv { + unsigned int keylen; + unsigned int plen; + unsigned int rlen; + int fail; + char key[32]; + char iv[8]; + char plaintext[16]; + char result[16]; +}; + +struct aes_tv aes_enc_tv_template[] = { + /* From FIPS-197 */ + { + 16, 16, 16, 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }, + }, + { + 24, 16, 16, 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }, + }, + { + 32, 16, 16, 0, + { 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 }, + { 0 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }, + }, +}; + +struct aes_tv aes_dec_tv_template[] = { + /* From FIPS-197 */ + { + 16, 16, 16, 0, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0 }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + + { + 24, 16, 16, 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0 }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + { + 32, 16, 16, 0, + { 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 }, + { 0 }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, +}; + +/* + * Compression stuff. + */ +#define COMP_BUF_SIZE 512 + +struct comp_testvec { + int inlen, outlen; + char input[COMP_BUF_SIZE]; + char output[COMP_BUF_SIZE]; +}; + +/* + * Deflate test vectors (null-terminated strings). + * Params: winbits=11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. + */ +#define DEFLATE_COMP_TEST_VECTORS 2 +#define DEFLATE_DECOMP_TEST_VECTORS 2 + +struct comp_testvec deflate_comp_tv_template[] = { + { + 70, 38, + + "Join us now and share the software " + "Join us now and share the software ", + + { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56, + 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51, + 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9, + 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07, + 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 + }, + }, + + { + 191, 122, + + "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + + { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04, + 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09, + 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8, + 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49, + 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27, + 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2, + 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad, + 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4, + 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b, + 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f, + 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf, + 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02, + 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98, + 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a, + 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79, + 0xfa, 0x02 }, + }, +}; + +struct comp_testvec deflate_decomp_tv_template[] = { + { + 122, 191, + + { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04, + 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09, + 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8, + 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49, + 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27, + 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2, + 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad, + 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4, + 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b, + 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f, + 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf, + 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02, + 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98, + 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a, + 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79, + 0xfa, 0x02 }, + + "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + }, + + { + 38, 70, + + { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56, + 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51, + 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9, + 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07, + 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 + }, + + "Join us now and share the software " + "Join us now and share the software ", + }, +}; + +#endif /* _CRYPTO_TCRYPT_H */ diff -Nru a/crypto/twofish.c b/crypto/twofish.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/twofish.c Wed Apr 23 17:09:06 2003 @@ -0,0 +1,900 @@ +/* + * Twofish for CryptoAPI + * + * Originaly Twofish for GPG + * By Matthew Skala , July 26, 1998 + * 256-bit key length added March 20, 1999 + * Some modifications to reduce the text size by Werner Koch, April, 1998 + * Ported to the kerneli patch by Marc Mutz + * Ported to CryptoAPI by Colin Slater + * + * The original author has disclaimed all copyright interest in this + * code and thus put it in the public domain. The subsequent authors + * have put this under the GNU General Public License. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * This code is a "clean room" implementation, written from the paper + * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, + * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available + * through http://www.counterpane.com/twofish.html + * + * For background information on multiplication in finite fields, used for + * the matrix operations in the key schedule, see the book _Contemporary + * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the + * Third Edition. + */ +#include +#include +#include +#include +#include + + +/* The large precomputed tables for the Twofish cipher (twofish.c) + * Taken from the same source as twofish.c + * Marc Mutz + */ + +/* These two tables are the q0 and q1 permutations, exactly as described in + * the Twofish paper. */ + +static const u8 q0[256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 +}; + +static const u8 q1[256] = { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +/* These MDS tables are actually tables of MDS composed with q0 and q1, + * because it is only ever used that way and we can save some time by + * precomputing. Of course the main saving comes from precomputing the + * GF(2^8) multiplication involved in the MDS matrix multiply; by looking + * things up in these tables we reduce the matrix multiply to four lookups + * and three XORs. Semi-formally, the definition of these tables is: + * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T + * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T + * where ^T means "transpose", the matrix multiply is performed in GF(2^8) + * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described + * by Schneier et al, and I'm casually glossing over the byte/word + * conversion issues. */ + +static const u32 mds[4][256] = { + {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, + 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, + 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, + 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, + 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, + 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, + 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, + 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, + 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, + 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, + 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, + 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, + 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, + 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, + 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, + 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, + 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, + 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, + 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, + 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, + 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, + 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, + 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, + 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, + 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, + 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, + 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, + 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, + 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, + 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, + 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, + 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, + 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, + 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, + 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, + 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, + 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, + 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, + 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, + 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, + 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, + 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, + 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, + + {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, + 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, + 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, + 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, + 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, + 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, + 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, + 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, + 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, + 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, + 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, + 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, + 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, + 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, + 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, + 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, + 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, + 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, + 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, + 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, + 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, + 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, + 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, + 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, + 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, + 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, + 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, + 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, + 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, + 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, + 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, + 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, + 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, + 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, + 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, + 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, + 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, + 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, + 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, + 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, + 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, + 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, + 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, + + {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, + 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, + 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, + 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, + 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, + 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, + 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, + 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, + 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, + 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, + 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, + 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, + 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, + 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, + 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, + 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, + 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, + 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, + 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, + 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, + 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, + 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, + 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, + 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, + 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, + 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, + 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, + 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, + 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, + 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, + 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, + 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, + 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, + 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, + 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, + 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, + 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, + 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, + 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, + 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, + 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, + 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, + 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, + + {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, + 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, + 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, + 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, + 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, + 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, + 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, + 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, + 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, + 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, + 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, + 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, + 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, + 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, + 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, + 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, + 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, + 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, + 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, + 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, + 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, + 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, + 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, + 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, + 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, + 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, + 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, + 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, + 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, + 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, + 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, + 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, + 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, + 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, + 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, + 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, + 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, + 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, + 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, + 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, + 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, + 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, + 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} +}; + +/* The exp_to_poly and poly_to_exp tables are used to perform efficient + * operations in GF(2^8) represented as GF(2)[x]/w(x) where + * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the + * definition of the RS matrix in the key schedule. Elements of that field + * are polynomials of degree not greater than 7 and all coefficients 0 or 1, + * which can be represented naturally by bytes (just substitute x=2). In that + * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) + * multiplication is inefficient without hardware support. To multiply + * faster, I make use of the fact x is a generator for the nonzero elements, + * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for + * some n in 0..254. Note that that caret is exponentiation in GF(2^8), + * *not* polynomial notation. So if I want to compute pq where p and q are + * in GF(2^8), I can just say: + * 1. if p=0 or q=0 then pq=0 + * 2. otherwise, find m and n such that p=x^m and q=x^n + * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq + * The translations in steps 2 and 3 are looked up in the tables + * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this + * in action, look at the CALC_S macro. As additional wrinkles, note that + * one of my operands is always a constant, so the poly_to_exp lookup on it + * is done in advance; I included the original values in the comments so + * readers can have some chance of recognizing that this *is* the RS matrix + * from the Twofish paper. I've only included the table entries I actually + * need; I never do a lookup on a variable input of zero and the biggest + * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll + * never sum to more than 491. I'm repeating part of the exp_to_poly table + * so that I don't have to do mod-255 reduction in the exponent arithmetic. + * Since I know my constant operands are never zero, I only have to worry + * about zero values in the variable operand, and I do it with a simple + * conditional branch. I know conditionals are expensive, but I couldn't + * see a non-horrible way of avoiding them, and I did manage to group the + * statements so that each if covers four group multiplications. */ + +static const u8 poly_to_exp[255] = { + 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, + 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, + 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, + 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, + 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, + 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, + 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, + 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, + 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, + 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, + 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, + 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, + 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, + 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, + 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, + 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, + 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, + 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, + 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, + 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, + 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, + 0x85, 0xC8, 0xA1 +}; + +static const u8 exp_to_poly[492] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, + 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, + 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, + 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, + 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, + 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, + 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, + 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, + 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, + 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, + 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, + 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, + 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, + 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, + 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, + 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, + 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, + 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, + 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, + 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, + 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, + 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, + 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, + 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, + 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, + 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, + 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, + 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, + 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, + 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, + 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, + 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, + 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, + 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, + 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, + 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, + 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, + 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB +}; + + +/* The table constants are indices of + * S-box entries, preprocessed through q0 and q1. */ +static const u8 calc_sb_tbl[512] = { + 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, + 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, + 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, + 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, + 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, + 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, + 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, + 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, + 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, + 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, + 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, + 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, + 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, + 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, + 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, + 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, + 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, + 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, + 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, + 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, + 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, + 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, + 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, + 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, + 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, + 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, + 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, + 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, + 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, + 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, + 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, + 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, + 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, + 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, + 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, + 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, + 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, + 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, + 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, + 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, + 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, + 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, + 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, + 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, + 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, + 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, + 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, + 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, + 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, + 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, + 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, + 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, + 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, + 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, + 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, + 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, + 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, + 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, + 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, + 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, + 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, + 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, + 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, + 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 +}; + +/* Macro to perform one column of the RS matrix multiplication. The + * parameters a, b, c, and d are the four bytes of output; i is the index + * of the key bytes, and w, x, y, and z, are the column of constants from + * the RS matrix, preprocessed through the poly_to_exp table. */ + +#define CALC_S(a, b, c, d, i, w, x, y, z) \ + if (key[i]) { \ + tmp = poly_to_exp[key[i] - 1]; \ + (a) ^= exp_to_poly[tmp + (w)]; \ + (b) ^= exp_to_poly[tmp + (x)]; \ + (c) ^= exp_to_poly[tmp + (y)]; \ + (d) ^= exp_to_poly[tmp + (z)]; \ + } + +/* Macros to calculate the key-dependent S-boxes for a 128-bit key using + * the S vector from CALC_S. CALC_SB_2 computes a single entry in all + * four S-boxes, where i is the index of the entry to compute, and a and b + * are the index numbers preprocessed through the q0 and q1 tables + * respectively. */ + +#define CALC_SB_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ + ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ + ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ + ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] + +/* Macro exactly like CALC_SB_2, but for 192-bit keys. */ + +#define CALC_SB192_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ + ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ + ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ + ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; + +/* Macro exactly like CALC_SB_2, but for 256-bit keys. */ + +#define CALC_SB256_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ + ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ + ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ + ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; + +/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the + * last two stages of the h() function for a given index (either 2i or 2i+1). + * a, b, c, and d are the four bytes going into the last two stages. For + * 128-bit keys, this is the entire h() function and a and c are the index + * preprocessed through q0 and q1 respectively; for longer keys they are the + * output of previous stages. j is the index of the first key byte to use. + * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 + * twice, doing the Psuedo-Hadamard Transform, and doing the necessary + * rotations. Its parameters are: a, the array to write the results into, + * j, the index of the first output entry, k and l, the preprocessed indices + * for index 2i, and m and n, the preprocessed indices for index 2i+1. + * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a, b, c and d are the + * four bytes going into the last three stages. For 192-bit keys, c = d + * are the index preprocessed through q0, and a = b are the index + * preprocessed through q1; j is the index of the first key byte to use. + * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro + * instead of CALC_K_2. + * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a and b are the index + * preprocessed through q0 and q1 respectively; j is the index of the first + * key byte to use. CALC_K256 is identical to CALC_K but for using the + * CALC_K256_2 macro instead of CALC_K_2. */ + +#define CALC_K_2(a, b, c, d, j) \ + mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ + ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ + ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ + ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] + +#define CALC_K(a, j, k, l, m, n) \ + x = CALC_K_2 (k, l, k, l, 0); \ + y = CALC_K_2 (m, n, m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K192_2(a, b, c, d, j) \ + CALC_K_2 (q0[a ^ key[(j) + 16]], \ + q1[b ^ key[(j) + 17]], \ + q0[c ^ key[(j) + 18]], \ + q1[d ^ key[(j) + 19]], j) + +#define CALC_K192(a, j, k, l, m, n) \ + x = CALC_K192_2 (l, l, k, k, 0); \ + y = CALC_K192_2 (n, n, m, m, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K256_2(a, b, j) \ + CALC_K192_2 (q1[b ^ key[(j) + 24]], \ + q1[a ^ key[(j) + 25]], \ + q0[a ^ key[(j) + 26]], \ + q0[b ^ key[(j) + 27]], j) + +#define CALC_K256(a, j, k, l, m, n) \ + x = CALC_K256_2 (k, l, 0); \ + y = CALC_K256_2 (m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + + +/* Macros to compute the g() function in the encryption and decryption + * rounds. G1 is the straight g() function; G2 includes the 8-bit + * rotation for the high 32-bit word. */ + +#define G1(a) \ + (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ + ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) + +#define G2(b) \ + (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ + ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) + +/* Encryption and decryption Feistel rounds. Each one calls the two g() + * macros, does the PHT, and performs the XOR and the appropriate bit + * rotations. The parameters are the round number (used to select subkeys), + * and the four 32-bit chunks of the text. */ + +#define ENCROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x + ctx->k[2 * (n) + 1]; \ + (c) ^= x + ctx->k[2 * (n)]; \ + (c) = ((c) >> 1) + ((c) << 31); \ + (d) = (((d) << 1)+((d) >> 31)) ^ y + +#define DECROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x; \ + (d) ^= y + ctx->k[2 * (n) + 1]; \ + (d) = ((d) >> 1) + ((d) << 31); \ + (c) = (((c) << 1)+((c) >> 31)); \ + (c) ^= (x + ctx->k[2 * (n)]) + +/* Encryption and decryption cycles; each one is simply two Feistel rounds + * with the 32-bit chunks re-ordered to simulate the "swap" */ + +#define ENCCYCLE(n) \ + ENCROUND (2 * (n), a, b, c, d); \ + ENCROUND (2 * (n) + 1, c, d, a, b) + +#define DECCYCLE(n) \ + DECROUND (2 * (n) + 1, c, d, a, b); \ + DECROUND (2 * (n), a, b, c, d) + +/* Macros to convert the input and output bytes into 32-bit words, + * and simultaneously perform the whitening step. INPACK packs word + * number n into the variable named by x, using whitening subkey number m. + * OUTUNPACK unpacks word number n from the variable named by x, using + * whitening subkey number m. */ + +#define INPACK(n, x, m) \ + x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ + ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + +#define OUTUNPACK(n, x, m) \ + x ^= ctx->w[m]; \ + out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ + out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + +#define TF_MIN_KEY_SIZE 16 +#define TF_MAX_KEY_SIZE 32 +#define TF_BLOCK_SIZE 16 + +/* Structure for an expanded Twofish key. s contains the key-dependent + * S-boxes composed with the MDS matrix; w contains the eight "whitening" + * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note + * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ +struct twofish_ctx { + u32 s[4][256], w[8], k[32]; +}; + +/* Perform the key setup. */ +static int twofish_setkey(void *cx, const u8 *key, + unsigned int key_len, u32 *flags) +{ + + struct twofish_ctx *ctx = cx; + + int i, j, k; + + /* Temporaries for CALC_K. */ + u32 x, y; + + /* The S vector used to key the S-boxes, split up into individual bytes. + * 128-bit keys use only sa through sh; 256-bit use all of them. */ + u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; + u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; + + /* Temporary for CALC_S. */ + u8 tmp; + + /* Check key length. */ + if (key_len != 16 && key_len != 24 && key_len != 32) + return -EINVAL; /* unsupported key length */ + + /* Compute the first two words of the S vector. The magic numbers are + * the entries of the RS matrix, preprocessed through poly_to_exp. The + * numbers in the comments are the original (polynomial form) matrix + * entries. */ + CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ + /* Calculate the third word of the S vector */ + CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + } + + if (key_len == 32) { /* 256-bit key */ + /* Calculate the fourth word of the S vector */ + CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else if (key_len == 24) { /* 192-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else { /* 128-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + + return 0; +} + +/* Encrypt one block. in and out may be the same. */ +static void twofish_encrypt(void *cx, u8 *out, const u8 *in) +{ + struct twofish_ctx *ctx = cx; + + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, a, 0); + INPACK (1, b, 1); + INPACK (2, c, 2); + INPACK (3, d, 3); + + /* Encryption Feistel cycles. */ + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, c, 4); + OUTUNPACK (1, d, 5); + OUTUNPACK (2, a, 6); + OUTUNPACK (3, b, 7); + +} + +/* Decrypt one block. in and out may be the same. */ +static void twofish_decrypt(void *cx, u8 *out, const u8 *in) +{ + struct twofish_ctx *ctx = cx; + + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, c, 4); + INPACK (1, d, 5); + INPACK (2, a, 6); + INPACK (3, b, 7); + + /* Encryption Feistel cycles. */ + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, a, 0); + OUTUNPACK (1, b, 1); + OUTUNPACK (2, c, 2); + OUTUNPACK (3, d, 3); + +} + +static struct crypto_alg alg = { + .cra_name = "twofish", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = TF_MIN_KEY_SIZE, + .cia_max_keysize = TF_MAX_KEY_SIZE, + .cia_ivsize = TF_BLOCK_SIZE, + .cia_setkey = twofish_setkey, + .cia_encrypt = twofish_encrypt, + .cia_decrypt = twofish_decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION ("Twofish Cipher Algorithm"); diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c Wed Apr 23 17:09:05 2003 +++ b/drivers/net/3c59x.c Wed Apr 23 17:09:05 2003 @@ -1997,7 +1997,7 @@ if (skb->ip_summed != CHECKSUM_HW) vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); else - vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum); + vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); if (!skb_shinfo(skb)->nr_frags) { vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, diff -Nru a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h --- a/include/asm-i386/kmap_types.h Wed Apr 23 17:09:06 2003 +++ b/include/asm-i386/kmap_types.h Wed Apr 23 17:09:06 2003 @@ -8,6 +8,8 @@ KM_PTE0, KM_PTE1, KM_PTE2, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff -Nru a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h --- a/include/asm-ppc/kmap_types.h Wed Apr 23 17:09:06 2003 +++ b/include/asm-ppc/kmap_types.h Wed Apr 23 17:09:06 2003 @@ -9,6 +9,8 @@ KM_USER0, KM_USER1, KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff -Nru a/include/asm-sparc/kmap_types.h b/include/asm-sparc/kmap_types.h --- a/include/asm-sparc/kmap_types.h Wed Apr 23 17:09:06 2003 +++ b/include/asm-sparc/kmap_types.h Wed Apr 23 17:09:06 2003 @@ -8,6 +8,8 @@ KM_USER0, KM_USER1, KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff -Nru a/include/asm-sparc64/kmap_types.h b/include/asm-sparc64/kmap_types.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-sparc64/kmap_types.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,20 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +/* Dummy header just to define km_type. None of this + * is actually used on sparc64. -DaveM + */ + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#endif diff -Nru a/include/asm-x86_64/kmap_types.h b/include/asm-x86_64/kmap_types.h --- a/include/asm-x86_64/kmap_types.h Wed Apr 23 17:09:06 2003 +++ b/include/asm-x86_64/kmap_types.h Wed Apr 23 17:09:06 2003 @@ -7,6 +7,8 @@ KM_USER1, KM_IRQ0, KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/crypto.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,379 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Möller. + * + * 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 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _LINUX_CRYPTO_H +#define _LINUX_CRYPTO_H + +#include +#include +#include +#include +#include +#include + +/* + * Algorithm masks and types. + */ +#define CRYPTO_ALG_TYPE_MASK 0x000000ff +#define CRYPTO_ALG_TYPE_CIPHER 0x00000001 +#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 +#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 + +/* + * Transform masks and values (for crt_flags). + */ +#define CRYPTO_TFM_MODE_MASK 0x000000ff +#define CRYPTO_TFM_REQ_MASK 0x000fff00 +#define CRYPTO_TFM_RES_MASK 0xfff00000 + +#define CRYPTO_TFM_MODE_ECB 0x00000001 +#define CRYPTO_TFM_MODE_CBC 0x00000002 +#define CRYPTO_TFM_MODE_CFB 0x00000004 +#define CRYPTO_TFM_MODE_CTR 0x00000008 + +#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 +#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 +#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 +#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 +#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 +#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 + +/* + * Miscellaneous stuff. + */ +#define CRYPTO_UNSPEC 0 +#define CRYPTO_MAX_ALG_NAME 64 + +struct scatterlist; + +/* + * Algorithms: modular crypto algorithm implementations, managed + * via crypto_register_alg() and crypto_unregister_alg(). + */ +struct cipher_alg { + unsigned int cia_min_keysize; + unsigned int cia_max_keysize; + unsigned int cia_ivsize; + int (*cia_setkey)(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags); + void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src); + void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src); +}; + +struct digest_alg { + unsigned int dia_digestsize; + void (*dia_init)(void *ctx); + void (*dia_update)(void *ctx, const u8 *data, unsigned int len); + void (*dia_final)(void *ctx, u8 *out); +}; + +struct compress_alg { + int (*coa_init)(void *ctx); + void (*coa_exit)(void *ctx); + int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define cra_cipher cra_u.cipher +#define cra_digest cra_u.digest +#define cra_compress cra_u.compress + +struct crypto_alg { + struct list_head cra_list; + u32 cra_flags; + unsigned int cra_blocksize; + unsigned int cra_ctxsize; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + + union { + struct cipher_alg cipher; + struct digest_alg digest; + struct compress_alg compress; + } cra_u; + + struct module *cra_module; +}; + +/* + * Algorithm registration interface. + */ +int crypto_register_alg(struct crypto_alg *alg); +int crypto_unregister_alg(struct crypto_alg *alg); + +/* + * Algorithm query interface. + */ +int crypto_alg_available(const char *name, u32 flags); + +/* + * Transforms: user-instantiated objects which encapsulate algorithms + * and core processing logic. Managed via crypto_alloc_tfm() and + * crypto_free_tfm(), as well as the various helpers below. + */ +struct crypto_tfm; + +struct cipher_tfm { + void *cit_iv; + u32 cit_mode; + int (*cit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); + int (*cit_encrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_encrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + int (*cit_decrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_decrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + void (*cit_xor_block)(u8 *dst, const u8 *src); +}; + +struct digest_tfm { + void (*dit_init)(struct crypto_tfm *tfm); + void (*dit_update)(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); + void (*dit_final)(struct crypto_tfm *tfm, u8 *out); + void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, + unsigned int nsg, u8 *out); +#ifdef CONFIG_CRYPTO_HMAC + void *dit_hmac_block; +#endif +}; + +struct compress_tfm { + int (*cot_compress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*cot_decompress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define crt_cipher crt_u.cipher +#define crt_digest crt_u.digest +#define crt_compress crt_u.compress + +struct crypto_tfm { + + u32 crt_flags; + + union { + struct cipher_tfm cipher; + struct digest_tfm digest; + struct compress_tfm compress; + } crt_u; + + struct crypto_alg *__crt_alg; +}; + +/* + * Transform user interface. + */ + +/* + * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. + * If that fails and the kernel supports dynamically loadable modules, it + * will then attempt to load a module of the same name or alias. A refcount + * is grabbed on the algorithm which is then associated with the new transform. + * + * crypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ +struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); +void crypto_free_tfm(struct crypto_tfm *tfm); + +/* + * Transform helpers which query the underlying algorithm. + */ +static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_name; +} + +static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + + if (alg->cra_module) + return alg->cra_module->name; + else + return NULL; +} + +static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; +} + +static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_min_keysize; +} + +static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_max_keysize; +} + +static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_ivsize; +} + +static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_blocksize; +} + +static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + return tfm->__crt_alg->cra_digest.dia_digestsize; +} + +/* + * API wrappers. + */ +static inline void crypto_digest_init(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_init(tfm); +} + +static inline void crypto_digest_update(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_update(tfm, sg, nsg); +} + +static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_final(tfm, out); +} + +static inline void crypto_digest_digest(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_digest(tfm, sg, nsg, out); +} + +static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_setkey(tfm, key, keylen); +} + +static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, + const u8 *src, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(tfm->crt_cipher.cit_iv, src, len); +} + +static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, + u8 *dst, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(dst, tfm->crt_cipher.cit_iv, len); +} + +static inline int crypto_comp_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); +} + +static inline int crypto_comp_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); +} + +/* + * HMAC support. + */ +#ifdef CONFIG_CRYPTO_HMAC +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out); +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out); +#endif /* CONFIG_CRYPTO_HMAC */ + +#endif /* _LINUX_CRYPTO_H */ + diff -Nru a/include/linux/in.h b/include/linux/in.h --- a/include/linux/in.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/in.h Wed Apr 23 17:09:06 2003 @@ -41,6 +41,7 @@ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ IPPROTO_AH = 51, /* Authentication Header protocol */ IPPROTO_COMP = 108, /* Compression Header protocol */ + IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ IPPROTO_RAW = 255, /* Raw IP packets */ IPPROTO_MAX @@ -67,6 +68,8 @@ #define IP_RECVTOS 13 #define IP_MTU 14 #define IP_FREEBIND 15 +#define IP_IPSEC_POLICY 16 +#define IP_XFRM_POLICY 17 /* BSD compatibility */ #define IP_RECVRETOPTS IP_RETOPTS diff -Nru a/include/linux/in6.h b/include/linux/in6.h --- a/include/linux/in6.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/in6.h Wed Apr 23 17:09:06 2003 @@ -180,5 +180,8 @@ #define IPV6_FLOWLABEL_MGR 32 #define IPV6_FLOWINFO_SEND 33 +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 + #endif diff -Nru a/include/linux/inetdevice.h b/include/linux/inetdevice.h --- a/include/linux/inetdevice.h Wed Apr 23 17:09:05 2003 +++ b/include/linux/inetdevice.h Wed Apr 23 17:09:05 2003 @@ -19,6 +19,8 @@ int tag; int arp_filter; int medium_id; + int no_xfrm; + int no_policy; void *sysctl; }; diff -Nru a/include/linux/ip.h b/include/linux/ip.h --- a/include/linux/ip.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/ip.h Wed Apr 23 17:09:06 2003 @@ -18,8 +18,6 @@ #define _LINUX_IP_H #include -/* SOL_IP socket options */ - #define IPTOS_TOS_MASK 0x1E #define IPTOS_TOS(tos) ((tos)&IPTOS_TOS_MASK) #define IPTOS_LOWDELAY 0x10 @@ -67,14 +65,6 @@ #define MAXTTL 255 #define IPDEFTTL 64 -/* struct timestamp, struct route and MAX_ROUTES are removed. - - REASONS: it is clear that nobody used them because: - - MAX_ROUTES value was wrong. - - "struct route" was wrong. - - "struct timestamp" had fatally misaligned bitfields and was completely unusable. - */ - #define IPOPT_OPTVAL 0 #define IPOPT_OLEN 1 #define IPOPT_OFFSET 2 @@ -133,6 +123,21 @@ __u32 saddr; __u32 daddr; /*The options start here. */ +}; + +struct ip_auth_hdr { + __u8 nexthdr; + __u8 hdrlen; /* This one is measured in 32 bit units! */ + __u16 reserved; + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 auth_data[0]; /* Variable len but >=4. Mind the 64 bit alignment! */ +}; + +struct ip_esp_hdr { + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 enc_data[0]; /* Variable len but >=8. Mind the 64 bit alignment! */ }; #endif /* _LINUX_IP_H */ diff -Nru a/include/linux/ipsec.h b/include/linux/ipsec.h --- a/include/linux/ipsec.h Wed Apr 23 17:09:05 2003 +++ b/include/linux/ipsec.h Wed Apr 23 17:09:05 2003 @@ -1,69 +1,46 @@ -/* - * Definitions for the SECurity layer - * - * Author: - * Robert Muchsel - * - * 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 - * 2 of the License, or (at your option) any later version. - */ - #ifndef _LINUX_IPSEC_H #define _LINUX_IPSEC_H -#include -#include -#include -#include - -/* Values for the set/getsockopt calls */ - -/* These defines are compatible with NRL IPv6, however their semantics - is different */ - -#define IPSEC_LEVEL_NONE -1 /* send plaintext, accept any */ -#define IPSEC_LEVEL_DEFAULT 0 /* encrypt/authenticate if possible */ - /* the default MUST be 0, because a */ - /* socket is initialized with 0's */ -#define IPSEC_LEVEL_USE 1 /* use outbound, don't require inbound */ -#define IPSEC_LEVEL_REQUIRE 2 /* require both directions */ -#define IPSEC_LEVEL_UNIQUE 2 /* for compatibility only */ - -#ifdef __KERNEL__ - -/* skb bit flags set on packet input processing */ - -#define RCV_SEC 0x0f /* options on receive */ -#define RCV_AUTH 0x01 /* was authenticated */ -#define RCV_CRYPT 0x02 /* was encrypted */ -#define RCV_TUNNEL 0x04 /* was tunneled */ -#define SND_SEC 0xf0 /* options on send, these are */ -#define SND_AUTH 0x10 /* currently unused */ -#define SND_CRYPT 0x20 -#define SND_TUNNEL 0x40 - -/* - * FIXME: ignores network encryption for now.. - */ - -#ifdef CONFIG_NET_SECURITY -static __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb) -{ - return ((sk->authentication < IPSEC_LEVEL_REQUIRE) || - (skb->security & RCV_AUTH)) && - ((sk->encryption < IPSEC_LEVEL_REQUIRE) || - (skb->security & RCV_CRYPT)); -} - -#else - -static __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb) -{ - return 1; -} -#endif /* CONFIG */ +/* The definitions, required to talk to KAME racoon IKE. */ + +#include + +#define IPSEC_PORT_ANY 0 +#define IPSEC_ULPROTO_ANY 255 +#define IPSEC_PROTO_ANY 255 + +enum { + IPSEC_MODE_ANY = 0, /* We do not support this for SA */ + IPSEC_MODE_TRANSPORT = 1, + IPSEC_MODE_TUNNEL = 2 +}; + +enum { + IPSEC_DIR_ANY = 0, + IPSEC_DIR_INBOUND = 1, + IPSEC_DIR_OUTBOUND = 2, + IPSEC_DIR_FWD = 3, /* It is our own */ + IPSEC_DIR_MAX = 4, + IPSEC_DIR_INVALID = 5 +}; + +enum { + IPSEC_POLICY_DISCARD = 0, + IPSEC_POLICY_NONE = 1, + IPSEC_POLICY_IPSEC = 2, + IPSEC_POLICY_ENTRUST = 3, + IPSEC_POLICY_BYPASS = 4 +}; + +enum { + IPSEC_LEVEL_DEFAULT = 0, + IPSEC_LEVEL_USE = 1, + IPSEC_LEVEL_REQUIRE = 2, + IPSEC_LEVEL_UNIQUE = 3 +}; + +#define IPSEC_MANUAL_REQID_MAX 0x3fff + +#define IPSEC_REPLAYWSIZE 32 -#endif /* __KERNEL__ */ #endif /* _LINUX_IPSEC_H */ diff -Nru a/include/linux/ipv6.h b/include/linux/ipv6.h --- a/include/linux/ipv6.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/ipv6.h Wed Apr 23 17:09:06 2003 @@ -73,6 +73,21 @@ #define rt0_type rt_hdr.type; }; +struct ipv6_auth_hdr { + __u8 nexthdr; + __u8 hdrlen; /* This one is measured in 32 bit units! */ + __u16 reserved; + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 auth_data[0]; /* Length variable but >=4. Mind the 64 bit alignment! */ +}; + +struct ipv6_esp_hdr { + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 enc_data[0]; /* Length variable but >=8. Mind the 64 bit alignment! */ +}; + /* * IPv6 fixed header * diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h --- a/include/linux/netdevice.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/netdevice.h Wed Apr 23 17:09:06 2003 @@ -89,6 +89,11 @@ #define MAX_HEADER (LL_MAX_HEADER + 48) #endif +/* Reserve 16byte aligned hard_header_len, but at least 16. + * Alternative is: dev->hard_header_len ? (dev->hard_header_len + 15)&~15 : 0 + */ +#define LL_RESERVED_SPACE(dev) (((dev)->hard_header_len&~15) + 16) + /* * Network device statistics. Akin to the 2.0 ether stats but * with byte counters. @@ -478,6 +483,7 @@ extern int dev_queue_xmit(struct sk_buff *skb); extern int register_netdevice(struct net_device *dev); extern int unregister_netdevice(struct net_device *dev); +extern void synchronize_net(void); extern int register_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb); extern int dev_new_index(void); diff -Nru a/include/linux/netlink.h b/include/linux/netlink.h --- a/include/linux/netlink.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/netlink.h Wed Apr 23 17:09:06 2003 @@ -7,6 +7,7 @@ #define NETLINK_FIREWALL 3 /* Firewalling hook */ #define NETLINK_TCPDIAG 4 /* TCP socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ +#define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_ARPD 8 #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ #define NETLINK_IP6_FW 13 @@ -86,6 +87,8 @@ #ifdef __KERNEL__ +#include + struct netlink_skb_parms { struct ucred creds; /* Skb credentials */ @@ -107,8 +110,8 @@ extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len)); extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); -extern void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, - __u32 group, int allocation); +extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, + __u32 group, int allocation); extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); extern int netlink_register_notifier(struct notifier_block *nb); extern int netlink_unregister_notifier(struct notifier_block *nb); diff -Nru a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/pfkeyv2.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,329 @@ +/* PF_KEY user interface, this is defined by rfc2367 so + * do not make arbitrary modifications or else this header + * file will not be compliant. + */ + +#ifndef _LINUX_PFKEY2_H +#define _LINUX_PFKEY2_H + +#include + +#define PF_KEY_V2 2 +#define PFKEYV2_REVISION 199806L + +struct sadb_msg { + uint8_t sadb_msg_version; + uint8_t sadb_msg_type; + uint8_t sadb_msg_errno; + uint8_t sadb_msg_satype; + uint16_t sadb_msg_len; + uint16_t sadb_msg_reserved; + uint32_t sadb_msg_seq; + uint32_t sadb_msg_pid; +} __attribute__((packed)); +/* sizeof(struct sadb_msg) == 16 */ + +struct sadb_ext { + uint16_t sadb_ext_len; + uint16_t sadb_ext_type; +} __attribute__((packed)); +/* sizeof(struct sadb_ext) == 4 */ + +struct sadb_sa { + uint16_t sadb_sa_len; + uint16_t sadb_sa_exttype; + uint32_t sadb_sa_spi; + uint8_t sadb_sa_replay; + uint8_t sadb_sa_state; + uint8_t sadb_sa_auth; + uint8_t sadb_sa_encrypt; + uint32_t sadb_sa_flags; +} __attribute__((packed)); +/* sizeof(struct sadb_sa) == 16 */ + +struct sadb_lifetime { + uint16_t sadb_lifetime_len; + uint16_t sadb_lifetime_exttype; + uint32_t sadb_lifetime_allocations; + uint64_t sadb_lifetime_bytes; + uint64_t sadb_lifetime_addtime; + uint64_t sadb_lifetime_usetime; +} __attribute__((packed)); +/* sizeof(struct sadb_lifetime) == 32 */ + +struct sadb_address { + uint16_t sadb_address_len; + uint16_t sadb_address_exttype; + uint8_t sadb_address_proto; + uint8_t sadb_address_prefixlen; + uint16_t sadb_address_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_address) == 8 */ + +struct sadb_key { + uint16_t sadb_key_len; + uint16_t sadb_key_exttype; + uint16_t sadb_key_bits; + uint16_t sadb_key_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_key) == 8 */ + +struct sadb_ident { + uint16_t sadb_ident_len; + uint16_t sadb_ident_exttype; + uint16_t sadb_ident_type; + uint16_t sadb_ident_reserved; + uint64_t sadb_ident_id; +} __attribute__((packed)); +/* sizeof(struct sadb_ident) == 16 */ + +struct sadb_sens { + uint16_t sadb_sens_len; + uint16_t sadb_sens_exttype; + uint32_t sadb_sens_dpd; + uint8_t sadb_sens_sens_level; + uint8_t sadb_sens_sens_len; + uint8_t sadb_sens_integ_level; + uint8_t sadb_sens_integ_len; + uint32_t sadb_sens_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_sens) == 16 */ + +/* followed by: + uint64_t sadb_sens_bitmap[sens_len]; + uint64_t sadb_integ_bitmap[integ_len]; */ + +struct sadb_prop { + uint16_t sadb_prop_len; + uint16_t sadb_prop_exttype; + uint8_t sadb_prop_replay; + uint8_t sadb_prop_reserved[3]; +} __attribute__((packed)); +/* sizeof(struct sadb_prop) == 8 */ + +/* followed by: + struct sadb_comb sadb_combs[(sadb_prop_len + + sizeof(uint64_t) - sizeof(struct sadb_prop)) / + sizeof(strut sadb_comb)]; */ + +struct sadb_comb { + uint8_t sadb_comb_auth; + uint8_t sadb_comb_encrypt; + uint16_t sadb_comb_flags; + uint16_t sadb_comb_auth_minbits; + uint16_t sadb_comb_auth_maxbits; + uint16_t sadb_comb_encrypt_minbits; + uint16_t sadb_comb_encrypt_maxbits; + uint32_t sadb_comb_reserved; + uint32_t sadb_comb_soft_allocations; + uint32_t sadb_comb_hard_allocations; + uint64_t sadb_comb_soft_bytes; + uint64_t sadb_comb_hard_bytes; + uint64_t sadb_comb_soft_addtime; + uint64_t sadb_comb_hard_addtime; + uint64_t sadb_comb_soft_usetime; + uint64_t sadb_comb_hard_usetime; +} __attribute__((packed)); +/* sizeof(struct sadb_comb) == 72 */ + +struct sadb_supported { + uint16_t sadb_supported_len; + uint16_t sadb_supported_exttype; + uint32_t sadb_supported_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_supported) == 8 */ + +/* followed by: + struct sadb_alg sadb_algs[(sadb_supported_len + + sizeof(uint64_t) - sizeof(struct sadb_supported)) / + sizeof(struct sadb_alg)]; */ + +struct sadb_alg { + uint8_t sadb_alg_id; + uint8_t sadb_alg_ivlen; + uint16_t sadb_alg_minbits; + uint16_t sadb_alg_maxbits; + uint16_t sadb_alg_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_alg) == 8 */ + +struct sadb_spirange { + uint16_t sadb_spirange_len; + uint16_t sadb_spirange_exttype; + uint32_t sadb_spirange_min; + uint32_t sadb_spirange_max; + uint32_t sadb_spirange_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_spirange) == 16 */ + +struct sadb_x_kmprivate { + uint16_t sadb_x_kmprivate_len; + uint16_t sadb_x_kmprivate_exttype; + u_int32_t sadb_x_kmprivate_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_x_kmprivate) == 8 */ + +struct sadb_x_sa2 { + uint16_t sadb_x_sa2_len; + uint16_t sadb_x_sa2_exttype; + uint8_t sadb_x_sa2_mode; + uint8_t sadb_x_sa2_reserved1; + uint16_t sadb_x_sa2_reserved2; + uint32_t sadb_x_sa2_sequence; + uint32_t sadb_x_sa2_reqid; +} __attribute__((packed)); +/* sizeof(struct sadb_x_sa2) == 16 */ + +struct sadb_x_policy { + uint16_t sadb_x_policy_len; + uint16_t sadb_x_policy_exttype; + uint16_t sadb_x_policy_type; + uint8_t sadb_x_policy_dir; + uint8_t sadb_x_policy_reserved; + uint32_t sadb_x_policy_id; + uint32_t sadb_x_policy_reserved2; +} __attribute__((packed)); +/* sizeof(struct sadb_x_policy) == 16 */ + +struct sadb_x_ipsecrequest { + uint16_t sadb_x_ipsecrequest_len; + uint16_t sadb_x_ipsecrequest_proto; + uint8_t sadb_x_ipsecrequest_mode; + uint8_t sadb_x_ipsecrequest_level; + uint16_t sadb_x_ipsecrequest_reqid; +} __attribute__((packed)); +/* sizeof(struct sadb_x_ipsecrequest) == 16 */ + +/* This defines the TYPE of Nat Traversal in use. Currently only one + * type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06 + */ +struct sadb_x_nat_t_type { + uint16_t sadb_x_nat_t_type_len; + uint16_t sadb_x_nat_t_type_exttype; + uint8_t sadb_x_nat_t_type_type; + uint8_t sadb_x_nat_t_type_reserved[3]; +} __attribute__((packed)); +/* sizeof(struct sadb_x_nat_t_type) == 8 */ + +/* Pass a NAT Traversal port (Source or Dest port) */ +struct sadb_x_nat_t_port { + uint16_t sadb_x_nat_t_port_len; + uint16_t sadb_x_nat_t_port_exttype; + uint16_t sadb_x_nat_t_port_port; + uint16_t sadb_x_nat_t_port_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_x_nat_t_port) == 8 */ + +/* Message types */ +#define SADB_RESERVED 0 +#define SADB_GETSPI 1 +#define SADB_UPDATE 2 +#define SADB_ADD 3 +#define SADB_DELETE 4 +#define SADB_GET 5 +#define SADB_ACQUIRE 6 +#define SADB_REGISTER 7 +#define SADB_EXPIRE 8 +#define SADB_FLUSH 9 +#define SADB_DUMP 10 +#define SADB_X_PROMISC 11 +#define SADB_X_PCHANGE 12 +#define SADB_X_SPDUPDATE 13 +#define SADB_X_SPDADD 14 +#define SADB_X_SPDDELETE 15 +#define SADB_X_SPDGET 16 +#define SADB_X_SPDACQUIRE 17 +#define SADB_X_SPDDUMP 18 +#define SADB_X_SPDFLUSH 19 +#define SADB_X_SPDSETIDX 20 +#define SADB_X_SPDEXPIRE 21 +#define SADB_X_SPDDELETE2 22 +#define SADB_X_NAT_T_NEW_MAPPING 23 +#define SADB_MAX 23 + +/* Security Association flags */ +#define SADB_SAFLAGS_PFS 1 + +/* Security Association states */ +#define SADB_SASTATE_LARVAL 0 +#define SADB_SASTATE_MATURE 1 +#define SADB_SASTATE_DYING 2 +#define SADB_SASTATE_DEAD 3 +#define SADB_SASTATE_MAX 3 + +/* Security Association types */ +#define SADB_SATYPE_UNSPEC 0 +#define SADB_SATYPE_AH 2 +#define SADB_SATYPE_ESP 3 +#define SADB_SATYPE_RSVP 5 +#define SADB_SATYPE_OSPFV2 6 +#define SADB_SATYPE_RIPV2 7 +#define SADB_SATYPE_MIP 8 +#define SADB_X_SATYPE_IPCOMP 9 +#define SADB_SATYPE_MAX 9 + +/* Authentication algorithms */ +#define SADB_AALG_NONE 0 +#define SADB_AALG_MD5HMAC 2 +#define SADB_AALG_SHA1HMAC 3 +#define SADB_X_AALG_SHA2_256HMAC 5 +#define SADB_X_AALG_SHA2_384HMAC 6 +#define SADB_X_AALG_SHA2_512HMAC 7 +#define SADB_X_AALG_RIPEMD160HMAC 8 +#define SADB_X_AALG_NULL 251 /* kame */ +#define SADB_AALG_MAX 251 + +/* Encryption algorithms */ +#define SADB_EALG_NONE 0 +#define SADB_EALG_DESCBC 1 +#define SADB_EALG_3DESCBC 2 +#define SADB_X_EALG_CASTCBC 6 +#define SADB_X_EALG_BLOWFISHCBC 7 +#define SADB_EALG_NULL 11 +#define SADB_X_EALG_AESCBC 12 +#define SADB_EALG_MAX 12 + +/* Compression algorithms */ +#define SADB_X_CALG_NONE 0 +#define SADB_X_CALG_OUI 1 +#define SADB_X_CALG_DEFLATE 2 +#define SADB_X_CALG_LZS 3 +#define SADB_X_CALG_LZJH 4 +#define SADB_X_CALG_MAX 4 + +/* Extension Header values */ +#define SADB_EXT_RESERVED 0 +#define SADB_EXT_SA 1 +#define SADB_EXT_LIFETIME_CURRENT 2 +#define SADB_EXT_LIFETIME_HARD 3 +#define SADB_EXT_LIFETIME_SOFT 4 +#define SADB_EXT_ADDRESS_SRC 5 +#define SADB_EXT_ADDRESS_DST 6 +#define SADB_EXT_ADDRESS_PROXY 7 +#define SADB_EXT_KEY_AUTH 8 +#define SADB_EXT_KEY_ENCRYPT 9 +#define SADB_EXT_IDENTITY_SRC 10 +#define SADB_EXT_IDENTITY_DST 11 +#define SADB_EXT_SENSITIVITY 12 +#define SADB_EXT_PROPOSAL 13 +#define SADB_EXT_SUPPORTED_AUTH 14 +#define SADB_EXT_SUPPORTED_ENCRYPT 15 +#define SADB_EXT_SPIRANGE 16 +#define SADB_X_EXT_KMPRIVATE 17 +#define SADB_X_EXT_POLICY 18 +#define SADB_X_EXT_SA2 19 +/* The next four entries are for setting up NAT Traversal */ +#define SADB_X_EXT_NAT_T_TYPE 20 +#define SADB_X_EXT_NAT_T_SPORT 21 +#define SADB_X_EXT_NAT_T_DPORT 22 +#define SADB_X_EXT_NAT_T_OA 23 +#define SADB_EXT_MAX 23 + +/* Identity Extension values */ +#define SADB_IDENTTYPE_RESERVED 0 +#define SADB_IDENTTYPE_PREFIX 1 +#define SADB_IDENTTYPE_FQDN 2 +#define SADB_IDENTTYPE_USERFQDN 3 +#define SADB_IDENTTYPE_MAX 3 + +#endif /* !(_LINUX_PFKEY2_H) */ diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h --- a/include/linux/rtnetlink.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/rtnetlink.h Wed Apr 23 17:09:06 2003 @@ -198,10 +198,11 @@ RTA_MULTIPATH, RTA_PROTOINFO, RTA_FLOW, - RTA_CACHEINFO + RTA_CACHEINFO, + RTA_SESSION, }; -#define RTA_MAX RTA_CACHEINFO +#define RTA_MAX RTA_SESSION #define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg)))) #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg)) @@ -284,6 +285,25 @@ #define RTAX_MAX RTAX_REORDERING +struct rta_session +{ + __u8 proto; + + union { + struct { + __u16 sport; + __u16 dport; + } ports; + + struct { + __u8 type; + __u8 code; + __u16 ident; + } icmpt; + + __u32 spi; + } u; +}; /********************************************************* @@ -559,7 +579,7 @@ extern struct rtnetlink_link * rtnetlink_links[NPROTO]; extern int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb); extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo); -extern int rtnetlink_put_metrics(struct sk_buff *skb, unsigned *metrics); +extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data); diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h --- a/include/linux/skbuff.h Wed Apr 23 17:09:05 2003 +++ b/include/linux/skbuff.h Wed Apr 23 17:09:05 2003 @@ -165,7 +165,8 @@ unsigned char *raw; } mac; - struct dst_entry *dst; + struct dst_entry *dst; + struct sec_path *sp; /* * This is the control buffer. It is free to use for every @@ -178,7 +179,7 @@ unsigned int len; /* Length of actual data */ unsigned int data_len; unsigned int csum; /* Checksum */ - unsigned char __unused, /* Dead field, may be reused */ + unsigned char local_df, cloned, /* head may be cloned (check refcnt to be sure). */ pkt_type, /* Packet class */ ip_summed; /* Driver fed us an IP checksum */ @@ -755,6 +756,15 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; +} + +static inline int skb_pagelen(const struct sk_buff *skb) +{ + int i, len = 0; + + for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) + len += skb_shinfo(skb)->frags[i].size; + return len + skb_headlen(skb); } #define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) out_of_line_bug(); } while (0) diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h Wed Apr 23 17:09:05 2003 +++ b/include/linux/sysctl.h Wed Apr 23 17:09:05 2003 @@ -342,6 +342,8 @@ NET_IPV4_CONF_TAG=12, NET_IPV4_CONF_ARPFILTER=13, NET_IPV4_CONF_MEDIUM_ID=14, + NET_IPV4_CONF_NOXFRM=15, + NET_IPV4_CONF_NOPOLICY=16, }; /* /proc/sys/net/ipv6 */ diff -Nru a/include/linux/udp.h b/include/linux/udp.h --- a/include/linux/udp.h Wed Apr 23 17:09:06 2003 +++ b/include/linux/udp.h Wed Apr 23 17:09:06 2003 @@ -17,6 +17,9 @@ #ifndef _LINUX_UDP_H #define _LINUX_UDP_H +#include +#include +#include struct udphdr { __u16 source; @@ -25,5 +28,11 @@ __u16 check; }; +/* UDP socket options */ +#define UDP_CORK 1 /* Never send partially complete segments */ +#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */ + +/* UDP encapsulation types */ +#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ #endif /* _LINUX_UDP_H */ diff -Nru a/include/linux/xfrm.h b/include/linux/xfrm.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/xfrm.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,217 @@ +#ifndef _LINUX_XFRM_H +#define _LINUX_XFRM_H + +#include + +/* All of the structures in this file may not change size as they are + * passed into the kernel from userspace via netlink sockets. + */ + +/* Structure to encapsulate addresses. I do not want to use + * "standard" structure. My apologies. + */ +typedef union +{ + __u32 a4; + __u32 a6[4]; +} xfrm_address_t; + +/* Ident of a specific xfrm_state. It is used on input to lookup + * the state by (spi,daddr,ah/esp) or to store information about + * spi, protocol and tunnel address on output. + */ +struct xfrm_id +{ + xfrm_address_t daddr; + __u32 spi; + __u8 proto; +}; + +/* Selector, used as selector both on policy rules (SPD) and SAs. */ + +struct xfrm_selector +{ + xfrm_address_t daddr; + xfrm_address_t saddr; + __u16 dport; + __u16 dport_mask; + __u16 sport; + __u16 sport_mask; + __u8 prefixlen_d; + __u8 prefixlen_s; + __u8 proto; + int ifindex; + uid_t user; +}; + +#define XFRM_INF (~(u64)0) + +struct xfrm_lifetime_cfg +{ + __u64 soft_byte_limit; + __u64 hard_byte_limit; + __u64 soft_packet_limit; + __u64 hard_packet_limit; + __u64 soft_add_expires_seconds; + __u64 hard_add_expires_seconds; + __u64 soft_use_expires_seconds; + __u64 hard_use_expires_seconds; +}; + +struct xfrm_lifetime_cur +{ + __u64 bytes; + __u64 packets; + __u64 add_time; + __u64 use_time; +}; + +struct xfrm_replay_state +{ + __u32 oseq; + __u32 seq; + __u32 bitmap; +}; + +struct xfrm_algo { + char alg_name[64]; + int alg_key_len; /* in bits */ + char alg_key[0]; +}; + +struct xfrm_stats { + __u32 replay_window; + __u32 replay; + __u32 integrity_failed; +}; + +enum +{ + XFRM_POLICY_IN = 0, + XFRM_POLICY_OUT = 1, + XFRM_POLICY_FWD = 2, + XFRM_POLICY_MAX = 3 +}; + +enum +{ + XFRM_SHARE_ANY, /* No limitations */ + XFRM_SHARE_SESSION, /* For this session only */ + XFRM_SHARE_USER, /* For this user only */ + XFRM_SHARE_UNIQUE /* Use once */ +}; + +/* Netlink configuration messages. */ +#define XFRM_MSG_BASE 0x10 + +#define XFRM_MSG_NEWSA (RTM_BASE + 0) +#define XFRM_MSG_DELSA (RTM_BASE + 1) +#define XFRM_MSG_GETSA (RTM_BASE + 2) + +#define XFRM_MSG_NEWPOLICY (RTM_BASE + 3) +#define XFRM_MSG_DELPOLICY (RTM_BASE + 4) +#define XFRM_MSG_GETPOLICY (RTM_BASE + 5) + +#define XFRM_MSG_ALLOCSPI (RTM_BASE + 6) +#define XFRM_MSG_ACQUIRE (RTM_BASE + 7) +#define XFRM_MSG_EXPIRE (RTM_BASE + 8) + +#define XFRM_MSG_MAX (XFRM_MSG_EXPIRE+1) + +struct xfrm_user_tmpl { + struct xfrm_id id; + xfrm_address_t saddr; + __u16 reqid; + __u8 mode; + __u8 share; + __u8 optional; + __u32 aalgos; + __u32 ealgos; + __u32 calgos; +}; + +struct xfrm_encap_tmpl { + __u16 encap_type; + __u16 encap_sport; + __u16 encap_dport; +}; + +/* Netlink message attributes. */ +enum xfrm_attr_type_t { + XFRMA_UNSPEC, + XFRMA_ALG_AUTH, /* struct xfrm_algo */ + XFRMA_ALG_CRYPT, /* struct xfrm_algo */ + XFRMA_ALG_COMP, /* struct xfrm_algo */ + XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */ + XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */ + +#define XFRMA_MAX XFRMA_TMPL +}; + +struct xfrm_usersa_info { + struct xfrm_selector sel; + struct xfrm_id id; + struct xfrm_lifetime_cfg lft; + struct xfrm_lifetime_cur curlft; + struct xfrm_stats stats; + __u32 seq; + __u16 family; + __u16 reqid; + __u8 mode; /* 0=transport,1=tunnel */ + __u8 replay_window; +}; + +struct xfrm_usersa_id { + xfrm_address_t saddr; + __u32 spi; + __u16 family; + __u8 proto; +}; + +struct xfrm_userspi_info { + struct xfrm_usersa_info info; + __u32 min; + __u32 max; +}; + +struct xfrm_userpolicy_info { + struct xfrm_selector sel; + struct xfrm_lifetime_cfg lft; + struct xfrm_lifetime_cur curlft; + __u32 priority; + __u32 index; + __u16 family; + __u8 dir; + __u8 action; +#define XFRM_POLICY_ALLOW 0 +#define XFRM_POLICY_BLOCK 1 + __u8 flags; +#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ + __u8 share; +}; + +struct xfrm_userpolicy_id { + struct xfrm_selector sel; + __u32 index; + __u8 dir; +}; + +struct xfrm_user_acquire { + struct xfrm_id id; + xfrm_address_t saddr; + struct xfrm_userpolicy_info policy; + __u32 aalgos; + __u32 ealgos; + __u32 calgos; + __u32 seq; +}; + +struct xfrm_user_expire { + struct xfrm_usersa_info state; + __u8 hard; +}; + +#define XFRMGRP_ACQUIRE 1 +#define XFRMGRP_EXPIRE 2 + +#endif /* _LINUX_XFRM_H */ diff -Nru a/include/net/ah.h b/include/net/ah.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/net/ah.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,32 @@ +#ifndef _NET_AH_H +#define _NET_AH_H + +#include + +struct ah_data +{ + u8 *key; + int key_len; + u8 *work_icv; + int icv_full_len; + int icv_trunc_len; + + void (*icv)(struct ah_data*, + struct sk_buff *skb, u8 *icv); + + struct crypto_tfm *tfm; +}; + +static inline void +ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) +{ + struct crypto_tfm *tfm = ahp->tfm; + + memset(auth_data, 0, ahp->icv_trunc_len); + crypto_hmac_init(tfm, ahp->key, &ahp->key_len); + skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update); + crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); + memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); +} + +#endif diff -Nru a/include/net/dn_route.h b/include/net/dn_route.h --- a/include/net/dn_route.h Wed Apr 23 17:09:05 2003 +++ b/include/net/dn_route.h Wed Apr 23 17:09:05 2003 @@ -122,7 +122,7 @@ if ((dst = sk->dst_cache) && !dst->obsolete) { try_again: skb->dst = dst_clone(dst); - dst->output(skb); + dst_output(skb); return; } diff -Nru a/include/net/dst.h b/include/net/dst.h --- a/include/net/dst.h Wed Apr 23 17:09:06 2003 +++ b/include/net/dst.h Wed Apr 23 17:09:06 2003 @@ -9,6 +9,7 @@ #define _NET_DST_H #include +#include #include /* @@ -22,6 +23,13 @@ #define DST_GC_INC (5*HZ) #define DST_GC_MAX (120*HZ) +/* Each dst_entry has reference count and sits in some parent list(s). + * When it is removed from parent list, it is "freed" (dst_free). + * After this it enters dead state (dst->obsolete > 0) and if its refcnt + * is zero, it can be destroyed immediately, otherwise it is added + * to gc list and garbage collector periodically checks the refcnt. + */ + struct sk_buff; struct dst_entry @@ -29,22 +37,22 @@ struct dst_entry *next; atomic_t __refcnt; /* client references */ int __use; + struct dst_entry *child; struct net_device *dev; int obsolete; int flags; #define DST_HOST 1 +#define DST_NOXFRM 2 +#define DST_NOPOLICY 4 +#define DST_NOHASH 8 unsigned long lastuse; unsigned long expires; - unsigned mxlock; - unsigned pmtu; - unsigned window; - unsigned rtt; - unsigned rttvar; - unsigned ssthresh; - unsigned cwnd; - unsigned advmss; - unsigned reordering; + unsigned short header_len; /* more space at head required */ + unsigned short trailer_len; /* space to reserve at tail */ + + u32 metrics[RTAX_MAX]; + struct dst_entry *path; unsigned long rate_last; /* rate limiting for ICMP */ unsigned long rate_tokens; @@ -53,6 +61,7 @@ struct neighbour *neighbour; struct hh_cache *hh; + struct xfrm_state *xfrm; int (*input)(struct sk_buff*); int (*output)(struct sk_buff*); @@ -75,11 +84,11 @@ int (*gc)(void); struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); - struct dst_entry * (*reroute)(struct dst_entry *, - struct sk_buff *); void (*destroy)(struct dst_entry *); struct dst_entry * (*negative_advice)(struct dst_entry *); void (*link_failure)(struct sk_buff *); + void (*update_pmtu)(struct dst_entry *dst, u32 mtu); + int (*get_mss)(struct dst_entry *dst, u32 mtu); int entry_size; atomic_t entries; @@ -88,6 +97,33 @@ #ifdef __KERNEL__ +static inline u32 +dst_metric(struct dst_entry *dst, int metric) +{ + return dst->metrics[metric-1]; +} + +static inline u32 +dst_path_metric(struct dst_entry *dst, int metric) +{ + return dst->path->metrics[metric-1]; +} + +static inline u32 +dst_pmtu(struct dst_entry *dst) +{ + u32 mtu = dst_path_metric(dst, RTAX_MTU); + /* Yes, _exactly_. This is paranoia. */ + barrier(); + return mtu; +} + +static inline int +dst_metric_locked(struct dst_entry *dst, int metric) +{ + return dst_metric(dst, RTAX_LOCK) & (1<__refcnt); @@ -104,22 +140,40 @@ static inline void dst_release(struct dst_entry * dst) { - if (dst) + if (dst) { + if (atomic_read(&dst->__refcnt) < 1) { + printk("BUG: dst underflow %d: %p\n", + atomic_read(&dst->__refcnt), + current_text_addr()); + } atomic_dec(&dst->__refcnt); + } +} + +/* Children define the path of the packet through the + * Linux networking. Thus, destinations are stackable. + */ + +static inline struct dst_entry *dst_pop(struct dst_entry *dst) +{ + struct dst_entry *child = dst_clone(dst->child); + + dst_release(dst); + return child; } extern void * dst_alloc(struct dst_ops * ops); extern void __dst_free(struct dst_entry * dst); -extern void dst_destroy(struct dst_entry * dst); +extern struct dst_entry *dst_destroy(struct dst_entry * dst); -static inline -void dst_free(struct dst_entry * dst) +static inline void dst_free(struct dst_entry * dst) { if (dst->obsolete > 1) return; if (!atomic_read(&dst->__refcnt)) { - dst_destroy(dst); - return; + dst = dst_destroy(dst); + if (!dst) + return; } __dst_free(dst); } @@ -155,8 +209,42 @@ dst->expires = expires; } +/* Output packet to network from transport. */ +static inline int dst_output(struct sk_buff *skb) +{ + int err; + + for (;;) { + err = skb->dst->output(skb); + + if (likely(err == 0)) + return err; + if (unlikely(err != NET_XMIT_BYPASS)) + return err; + } +} + +/* Input packet from network to transport. */ +static inline int dst_input(struct sk_buff *skb) +{ + int err; + + for (;;) { + err = skb->dst->input(skb); + + if (likely(err == 0)) + return err; + /* Oh, Jamal... Seems, I will not forgive you this mess. :-) */ + if (unlikely(err != NET_XMIT_BYPASS)) + return err; + } +} + extern void dst_init(void); +struct flowi; +extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, + struct sock *sk, int flags); #endif #endif /* _NET_DST_H */ diff -Nru a/include/net/esp.h b/include/net/esp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/net/esp.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,54 @@ +#ifndef _NET_ESP_H +#define _NET_ESP_H + +#include + +struct esp_data +{ + /* Confidentiality */ + struct { + u8 *key; /* Key */ + int key_len; /* Key length */ + u8 *ivec; /* ivec buffer */ + /* ivlen is offset from enc_data, where encrypted data start. + * It is logically different of crypto_tfm_alg_ivsize(tfm). + * We assume that it is either zero (no ivec), or + * >= crypto_tfm_alg_ivsize(tfm). */ + int ivlen; + int padlen; /* 0..255 */ + struct crypto_tfm *tfm; /* crypto handle */ + } conf; + + /* Integrity. It is active when icv_full_len != 0 */ + struct { + u8 *key; /* Key */ + int key_len; /* Length of the key */ + u8 *work_icv; + int icv_full_len; + int icv_trunc_len; + void (*icv)(struct esp_data*, + struct sk_buff *skb, + int offset, int len, u8 *icv); + struct crypto_tfm *tfm; + } auth; +}; + +extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len); +extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); +extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); + +static inline void +esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, + int len, u8 *auth_data) +{ + struct crypto_tfm *tfm = esp->auth.tfm; + char *icv = esp->auth.work_icv; + + memset(auth_data, 0, esp->auth.icv_trunc_len); + crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); + skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); + crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); + memcpy(auth_data, icv, esp->auth.icv_trunc_len); +} + +#endif diff -Nru a/include/net/flow.h b/include/net/flow.h --- a/include/net/flow.h Wed Apr 23 17:09:06 2003 +++ b/include/net/flow.h Wed Apr 23 17:09:06 2003 @@ -1,6 +1,6 @@ /* * - * Flow based forwarding rules (usage: firewalling, etc) + * Generic internet FLOW. * */ @@ -8,12 +8,16 @@ #define _NET_FLOW_H struct flowi { - int proto; /* {TCP, UDP, ICMP} */ + int oif; + int iif; union { struct { __u32 daddr; __u32 saddr; + __u32 fwmark; + __u8 tos; + __u8 scope; } ip4_u; struct { @@ -27,9 +31,12 @@ #define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl4_dst nl_u.ip4_u.daddr #define fl4_src nl_u.ip4_u.saddr +#define fl4_fwmark nl_u.ip4_u.fwmark +#define fl4_tos nl_u.ip4_u.tos +#define fl4_scope nl_u.ip4_u.scope - int oif; - + __u8 proto; + __u8 flags; union { struct { __u16 sport; @@ -41,61 +48,12 @@ __u8 code; } icmpt; - unsigned long data; + __u32 spi; } uli_u; +#define fl_ip_sport uli_u.ports.sport +#define fl_ip_dport uli_u.ports.dport +#define fl_icmp_type uli_u.icmpt.type +#define fl_icmp_code uli_u.icmpt.code +#define fl_ipsec_spi uli_u.spi }; - -#define FLOWR_NODECISION 0 /* rule not appliable to flow */ -#define FLOWR_SELECT 1 /* flow must follow this rule */ -#define FLOWR_CLEAR 2 /* priority level clears flow */ -#define FLOWR_ERROR 3 - -struct fl_acc_args { - int type; - - -#define FL_ARG_FORWARD 1 -#define FL_ARG_ORIGIN 2 - - union { - struct sk_buff *skb; - struct { - struct sock *sk; - struct flowi *flow; - } fl_o; - } fl_u; -}; - - -struct pkt_filter { - atomic_t refcnt; - unsigned int offset; - __u32 value; - __u32 mask; - struct pkt_filter *next; -}; - -#define FLR_INPUT 1 -#define FLR_OUTPUT 2 - -struct flow_filter { - int type; - union { - struct pkt_filter *filter; - struct sock *sk; - } u; -}; - -struct flow_rule { - struct flow_rule_ops *ops; - unsigned char private[0]; -}; - -struct flow_rule_ops { - int (*accept)(struct rt6_info *rt, - struct rt6_info *rule, - struct fl_acc_args *args, - struct rt6_info **nrt); -}; - #endif diff -Nru a/include/net/ip.h b/include/net/ip.h --- a/include/net/ip.h Wed Apr 23 17:09:06 2003 +++ b/include/net/ip.h Wed Apr 23 17:09:06 2003 @@ -97,16 +97,19 @@ extern void ip_send_check(struct iphdr *ip); extern int ip_queue_xmit(struct sk_buff *skb); extern void ip_init(void); -extern int ip_build_xmit(struct sock *sk, - int getfrag (const void *, - char *, - unsigned int, - unsigned int), - const void *frag, - unsigned length, - struct ipcm_cookie *ipc, - struct rtable *rt, - int flags); +extern int ip_append_data(struct sock *sk, + int getfrag(void *from, char *to, int offset, int len, + int odd, struct sk_buff *skb), + void *from, int len, int protolen, + struct ipcm_cookie *ipc, + struct rtable *rt, + unsigned int flags); +extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb); +extern ssize_t ip_append_page(struct sock *sk, struct page *page, + int offset, size_t size, int flags); +extern int ip_push_pending_frames(struct sock *sk); +extern void ip_flush_pending_frames(struct sock *sk); + /* * Map a multicast IP onto multicast MAC for type Token Ring. @@ -126,8 +129,7 @@ } struct ip_reply_arg { - struct iovec iov[2]; - int n_iov; /* redundant */ + struct iovec iov[1]; u32 csum; int csumoffset; /* u16 offset of csum in iov[0].iov_base */ /* -1 if not needed */ @@ -159,14 +161,6 @@ extern int sysctl_ip_default_ttl; #ifdef CONFIG_INET -static inline int ip_send(struct sk_buff *skb) -{ - if (skb->len > skb->dst->pmtu) - return ip_fragment(skb, ip_finish_output); - else - return ip_finish_output(skb); -} - /* The function in 2.2 was invalid, producing wrong result for * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ static inline @@ -183,7 +177,7 @@ { return (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_DO || (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_WANT && - !(dst->mxlock&(1< - -struct ip6_fw_rule { - struct flow_rule flowr; - struct ip6_fw_rule *next; - struct ip6_fw_rule *prev; - struct flowi info; - unsigned long policy; -}; - -#endif - -#endif diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h --- a/include/net/ip6_route.h Wed Apr 23 17:09:06 2003 +++ b/include/net/ip6_route.h Wed Apr 23 17:09:06 2003 @@ -60,6 +60,8 @@ struct in6_addr *saddr, int oif, int flags); +extern struct rt6_info *ip6_dst_alloc(void); + /* * support functions for ND * diff -Nru a/include/net/ip_fib.h b/include/net/ip_fib.h --- a/include/net/ip_fib.h Wed Apr 23 17:09:06 2003 +++ b/include/net/ip_fib.h Wed Apr 23 17:09:06 2003 @@ -17,6 +17,7 @@ #define _NET_IP_FIB_H #include +#include struct kern_rta { @@ -65,7 +66,7 @@ int fib_protocol; u32 fib_prefsrc; u32 fib_priority; - unsigned fib_metrics[RTAX_MAX]; + u32 fib_metrics[RTAX_MAX]; #define fib_mtu fib_metrics[RTAX_MTU-1] #define fib_window fib_metrics[RTAX_WINDOW-1] #define fib_rtt fib_metrics[RTAX_RTT-1] @@ -117,7 +118,7 @@ { unsigned char tb_id; unsigned tb_stamp; - int (*tb_lookup)(struct fib_table *tb, const struct rt_key *key, struct fib_result *res); + int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); int (*tb_insert)(struct fib_table *table, struct rtmsg *r, struct kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req); @@ -130,7 +131,7 @@ int (*tb_get_info)(struct fib_table *table, char *buf, int first, int count); void (*tb_select_default)(struct fib_table *table, - const struct rt_key *key, struct fib_result *res); + const struct flowi *flp, struct fib_result *res); unsigned char tb_data[0]; }; @@ -152,18 +153,18 @@ return fib_get_table(id); } -static inline int fib_lookup(const struct rt_key *key, struct fib_result *res) +static inline int fib_lookup(const struct flowi *flp, struct fib_result *res) { - if (local_table->tb_lookup(local_table, key, res) && - main_table->tb_lookup(main_table, key, res)) + if (local_table->tb_lookup(local_table, flp, res) && + main_table->tb_lookup(main_table, flp, res)) return -ENETUNREACH; return 0; } -static inline void fib_select_default(const struct rt_key *key, struct fib_result *res) +static inline void fib_select_default(const struct flowi *flp, struct fib_result *res) { if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) - main_table->tb_select_default(main_table, key, res); + main_table->tb_select_default(main_table, flp, res); } #else /* CONFIG_IP_MULTIPLE_TABLES */ @@ -171,7 +172,7 @@ #define main_table (fib_tables[RT_TABLE_MAIN]) extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; -extern int fib_lookup(const struct rt_key *key, struct fib_result *res); +extern int fib_lookup(const struct flowi *flp, struct fib_result *res); extern struct fib_table *__fib_new_table(int id); extern void fib_rule_put(struct fib_rule *r); @@ -191,7 +192,7 @@ return fib_tables[id] ? : __fib_new_table(id); } -extern void fib_select_default(const struct rt_key *key, struct fib_result *res); +extern void fib_select_default(const struct flowi *flp, struct fib_result *res); #endif /* CONFIG_IP_MULTIPLE_TABLES */ @@ -204,13 +205,13 @@ extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb); extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, struct net_device *dev, u32 *spec_dst, u32 *itag); -extern void fib_select_multipath(const struct rt_key *key, struct fib_result *res); +extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); /* Exported by fib_semantics.c */ extern int ip_fib_check_default(u32 gw, struct net_device *dev); extern void fib_release_info(struct fib_info *); extern int fib_semantic_match(int type, struct fib_info *, - const struct rt_key *, struct fib_result*); + const struct flowi *, struct fib_result*); extern struct fib_info *fib_create_info(const struct rtmsg *r, struct kern_rta *rta, const struct nlmsghdr *, int *err); extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi); diff -Nru a/include/net/ipip.h b/include/net/ipip.h --- a/include/net/ipip.h Wed Apr 23 17:09:06 2003 +++ b/include/net/ipip.h Wed Apr 23 17:09:06 2003 @@ -34,7 +34,7 @@ ip_select_ident(iph, &rt->u.dst, NULL); \ ip_send_check(iph); \ \ - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, do_ip_send); \ + err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\ if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \ stats->tx_bytes += pkt_len; \ stats->tx_packets++; \ diff -Nru a/include/net/ipv6.h b/include/net/ipv6.h --- a/include/net/ipv6.h Wed Apr 23 17:09:06 2003 +++ b/include/net/ipv6.h Wed Apr 23 17:09:06 2003 @@ -198,11 +198,7 @@ extern int ip6_call_ra_chain(struct sk_buff *skb, int sel); -extern int ipv6_reassembly(struct sk_buff **skb, int); - extern int ipv6_parse_hopopts(struct sk_buff *skb, int); - -extern int ipv6_parse_exthdrs(struct sk_buff **skb, int); extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); diff -Nru a/include/net/protocol.h b/include/net/protocol.h --- a/include/net/protocol.h Wed Apr 23 17:09:06 2003 +++ b/include/net/protocol.h Wed Apr 23 17:09:06 2003 @@ -30,7 +30,7 @@ #include #endif -#define MAX_INET_PROTOS 32 /* Must be a power of 2 */ +#define MAX_INET_PROTOS 256 /* Must be a power of 2 */ /* This is used to register protocols. */ @@ -38,29 +38,23 @@ { int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); - struct inet_protocol *next; - unsigned char protocol; - unsigned char copy:1; - void *data; - const char *name; + int no_policy; }; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_protocol { - int (*handler)(struct sk_buff *skb); + int (*handler)(struct sk_buff **skb, unsigned int *nhoffp); void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __u32 info); - struct inet6_protocol *next; - unsigned char protocol; - unsigned char copy:1; - void *data; - const char *name; + unsigned int flags; /* INET6_PROTO_xxx */ }; +#define INET6_PROTO_NOPOLICY 0x1 +#define INET6_PROTO_FINAL 0x2 #endif /* This is used to register socket interfaces for IP protocols. */ @@ -93,14 +87,14 @@ extern struct list_head inetsw6[SOCK_MAX]; #endif -extern void inet_add_protocol(struct inet_protocol *prot); -extern int inet_del_protocol(struct inet_protocol *prot); +extern int inet_add_protocol(struct inet_protocol *prot, unsigned char num); +extern int inet_del_protocol(struct inet_protocol *prot, unsigned char num); extern void inet_register_protosw(struct inet_protosw *p); extern void inet_unregister_protosw(struct inet_protosw *p); #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) -extern void inet6_add_protocol(struct inet6_protocol *prot); -extern int inet6_del_protocol(struct inet6_protocol *prot); +extern int inet6_add_protocol(struct inet6_protocol *prot, unsigned char num); +extern int inet6_del_protocol(struct inet6_protocol *prot, unsigned char num); extern void inet6_register_protosw(struct inet_protosw *p); extern void inet6_unregister_protosw(struct inet_protosw *p); #endif diff -Nru a/include/net/raw.h b/include/net/raw.h --- a/include/net/raw.h Wed Apr 23 17:09:06 2003 +++ b/include/net/raw.h Wed Apr 23 17:09:06 2003 @@ -37,6 +37,6 @@ unsigned long raddr, unsigned long laddr, int dif); -extern struct sock *raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash); +extern void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash); #endif /* _RAW_H */ diff -Nru a/include/net/rawv6.h b/include/net/rawv6.h --- a/include/net/rawv6.h Wed Apr 23 17:09:06 2003 +++ b/include/net/rawv6.h Wed Apr 23 17:09:06 2003 @@ -7,9 +7,7 @@ extern struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE]; extern rwlock_t raw_v6_lock; -extern struct sock * ipv6_raw_deliver(struct sk_buff *skb, - int nexthdr); - +extern void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr); extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, struct in6_addr *loc_addr, struct in6_addr *rmt_addr); diff -Nru a/include/net/route.h b/include/net/route.h --- a/include/net/route.h Wed Apr 23 17:09:05 2003 +++ b/include/net/route.h Wed Apr 23 17:09:05 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,19 +46,6 @@ #define RT_CONN_FLAGS(sk) (RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute) -struct rt_key -{ - __u32 dst; - __u32 src; - int iif; - int oif; -#ifdef CONFIG_IP_ROUTE_FWMARK - __u32 fwmark; -#endif - __u8 tos; - __u8 scope; -}; - struct inet_peer; struct rtable { @@ -78,7 +66,7 @@ __u32 rt_gateway; /* Cache lookup keys */ - struct rt_key key; + struct flowi fl; /* Miscellaneous cached information */ __u32 rt_spec_dst; /* RFC1122 specific destination */ @@ -124,10 +112,11 @@ u32 src, u8 tos, struct net_device *dev); extern void ip_rt_advice(struct rtable **rp, int advice); extern void rt_cache_flush(int how); -extern int ip_route_output_key(struct rtable **, const struct rt_key *key); +extern int __ip_route_output_key(struct rtable **, const struct flowi *flp); +extern int ip_route_output_key(struct rtable **, struct flowi *flp); +extern int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin); extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu); -extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu); extern void ip_rt_send_redirect(struct sk_buff *skb); extern unsigned inet_addr_type(u32 addr); @@ -136,16 +125,6 @@ extern void ip_rt_get_source(u8 *src, struct rtable *rt); extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); -/* Deprecated: use ip_route_output_key directly */ -static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) -{ - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; - - return ip_route_output_key(rp, &key); -} - - static inline void ip_rt_put(struct rtable * rt) { if (rt) @@ -161,17 +140,47 @@ return ip_tos2prio[IPTOS_TOS(tos)>>1]; } -static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif) -{ +static inline int ip_route_connect(struct rtable **rp, u32 dst, + u32 src, u32 tos, int oif, u8 protocol, + u16 sport, u16 dport, struct sock *sk) +{ + struct flowi fl = { .oif = oif, + .nl_u = { .ip4_u = { .daddr = dst, + .saddr = src, + .tos = tos } }, + .proto = protocol, + .uli_u = { .ports = + { .sport = sport, + .dport = dport } } }; + int err; - err = ip_route_output(rp, dst, src, tos, oif); - if (err || (dst && src)) - return err; - dst = (*rp)->rt_dst; - src = (*rp)->rt_src; - ip_rt_put(*rp); - *rp = NULL; - return ip_route_output(rp, dst, src, tos, oif); + if (!dst || !src) { + err = __ip_route_output_key(rp, &fl); + if (err) + return err; + fl.fl4_dst = (*rp)->rt_dst; + fl.fl4_src = (*rp)->rt_src; + ip_rt_put(*rp); + *rp = NULL; + } + return ip_route_output_flow(rp, &fl, sk, 0); +} + +static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, + struct sock *sk) +{ + if (sport != (*rp)->fl.fl_ip_sport || + dport != (*rp)->fl.fl_ip_dport) { + struct flowi fl; + + memcpy(&fl, &(*rp)->fl, sizeof(fl)); + fl.fl_ip_sport = sport; + fl.fl_ip_dport = dport; + ip_rt_put(*rp); + *rp = NULL; + return ip_route_output_flow(rp, &fl, sk, 0); + } + return 0; } extern void rt_bind_peer(struct rtable *rt, int create); diff -Nru a/include/net/sock.h b/include/net/sock.h --- a/include/net/sock.h Wed Apr 23 17:09:06 2003 +++ b/include/net/sock.h Wed Apr 23 17:09:06 2003 @@ -221,7 +221,24 @@ int mc_index; /* Multicast device index */ __u32 mc_addr; struct ip_mc_socklist *mc_list; /* Group array */ + struct page *sndmsg_page; /* Cached page for sendmsg */ + u32 sndmsg_off; /* Cached offset for sendmsg */ + /* + * Following members are used to retain the infomation to build + * an ip header on each ip fragmentation while the socket is corked. + */ + struct { + unsigned int flags; + unsigned int fragsize; + struct ip_options *opt; + struct rtable *rt; + int length; /* Total length of all frames */ + u32 addr; + } cork; }; + +#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */ + #endif #if defined(CONFIG_PPPOE) || defined (CONFIG_PPPOE_MODULE) @@ -247,6 +264,14 @@ #define pppoe_relay proto.pppoe.relay #endif +#if defined(CONFIG_NET_KEY) || defined(CONFIG_NET_KEY_MODULE) +struct pfkey_opt { + int registered; + int promisc; +}; +#define pfkey_sk(__sk) ((__sk)->protinfo.pf_key) +#endif + /* This defines a selective acknowledgement block. */ struct tcp_sack_block { __u32 start_seq; @@ -304,6 +329,7 @@ __u16 mss_cache; /* Cached effective mss, not including SACKS */ __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ __u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */ + __u16 ext2_header_len;/* Options depending on route */ __u8 ca_state; /* State of fast-retransmit machine */ __u8 retransmits; /* Number of unrecovered RTO timeouts. */ @@ -344,8 +370,6 @@ struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */ struct sk_buff *send_head; /* Front of stuff to transmit */ - struct page *sndmsg_page; /* Cached page for sendmsg */ - u32 sndmsg_off; /* Cached offset for sendmsg */ __u32 rcv_wnd; /* Current receiver window */ __u32 rcv_wup; /* rcv_nxt on last window update sent */ @@ -431,6 +455,20 @@ unsigned long last_synq_overflow; }; +struct udp_opt { + int pending; /* Any pending frames ? */ + unsigned int corkflag; /* Cork is required */ + __u16 encap_type; /* Is this an Encapsulation socket? */ + /* + * Following members retains the infomation to create a UDP header + * when the socket is uncorked. + */ + u32 saddr; /* source address */ + u32 daddr; /* destination address */ + __u16 sport; /* source port */ + __u16 dport; /* destination port */ + __u16 len; /* total length of pending frames */ +}; /* * This structure really needs to be cleaned up. @@ -526,6 +564,7 @@ wait_queue_head_t *sleep; /* Sock wait queue */ struct dst_entry *dst_cache; /* Destination cache */ rwlock_t dst_lock; + struct xfrm_policy *policy[2]; atomic_t rmem_alloc; /* Receive queue bytes committed */ struct sk_buff_head receive_queue; /* Incoming packets */ atomic_t wmem_alloc; /* Transmit queue bytes committed */ @@ -586,6 +625,7 @@ union { struct tcp_opt af_tcp; + struct udp_opt af_udp; #if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE) struct raw_opt tp_raw4; #endif @@ -597,6 +637,8 @@ #endif /* CONFIG_SPX */ } tp_pinfo; +#define tcp_sk(sk) (&(sk)->tp_pinfo.af_tcp) +#define udp_sk(sk) (&(sk)->tp_pinfo.af_udp) int err, err_soft; /* Soft holds errors that don't cause failure but are the cause @@ -667,8 +709,11 @@ #if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE) struct wanpipe_opt *af_wanpipe; #endif +#if defined(CONFIG_NET_KEY) || defined(CONFIG_NET_KEY_MODULE) + struct pfkey_opt *pf_key; +#endif } protinfo; - +#define inet_sk(sk) (&(sk)->protinfo.af_inet) /* This part is used for the timeout functions. */ struct timer_list timer; /* This is the sock cleanup timer. */ @@ -732,6 +777,8 @@ int (*recvmsg)(struct sock *sk, struct msghdr *msg, int len, int noblock, int flags, int *addr_len); + int (*sendpage)(struct sock *sk, struct page *page, + int offset, size_t size, int flags); int (*bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len); diff -Nru a/include/net/tcp.h b/include/net/tcp.h --- a/include/net/tcp.h Wed Apr 23 17:09:05 2003 +++ b/include/net/tcp.h Wed Apr 23 17:09:05 2003 @@ -907,9 +907,12 @@ struct dst_entry *dst = __sk_dst_get(sk); int mss_now = tp->mss_cache; - if (dst && dst->pmtu != tp->pmtu_cookie) - mss_now = tcp_sync_mss(sk, dst->pmtu); - + if (dst) { + u32 mtu = dst_pmtu(dst); + if (mtu != tp->pmtu_cookie || + tp->ext2_header_len != dst->header_len) + mss_now = tcp_sync_mss(sk, mtu); + } if (tp->eff_sacks) mss_now -= (TCPOLEN_SACK_BASE_ALIGNED + (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK)); diff -Nru a/include/net/transp_v6.h b/include/net/transp_v6.h --- a/include/net/transp_v6.h Wed Apr 23 17:09:06 2003 +++ b/include/net/transp_v6.h Wed Apr 23 17:09:06 2003 @@ -15,6 +15,14 @@ struct flowi; +/* extention headers */ +extern void ipv6_hopopts_init(void); +extern void ipv6_rthdr_init(void); +extern void ipv6_frag_init(void); +extern void ipv6_nodata_init(void); +extern void ipv6_destopt_init(void); + +/* transport protocols */ extern void rawv6_init(void); extern void udpv6_init(void); extern void tcpv6_init(void); diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/net/xfrm.h Wed Apr 23 17:09:06 2003 @@ -0,0 +1,818 @@ +#ifndef _NET_XFRM_H +#define _NET_XFRM_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define XFRM_ALIGN8(len) (((len) + 7) & ~7) + +extern struct semaphore xfrm_cfg_sem; + +/* Organization of SPD aka "XFRM rules" + ------------------------------------ + + Basic objects: + - policy rule, struct xfrm_policy (=SPD entry) + - bundle of transformations, struct dst_entry == struct xfrm_dst (=SA bundle) + - instance of a transformer, struct xfrm_state (=SA) + - template to clone xfrm_state, struct xfrm_tmpl + + SPD is plain linear list of xfrm_policy rules, ordered by priority. + (To be compatible with existing pfkeyv2 implementations, + many rules with priority of 0x7fffffff are allowed to exist and + such rules are ordered in an unpredictable way, thanks to bsd folks.) + + Lookup is plain linear search until the first match with selector. + + If "action" is "block", then we prohibit the flow, otherwise: + if "xfrms_nr" is zero, the flow passes untransformed. Otherwise, + policy entry has list of up to XFRM_MAX_DEPTH transformations, + described by templates xfrm_tmpl. Each template is resolved + to a complete xfrm_state (see below) and we pack bundle of transformations + to a dst_entry returned to requestor. + + dst -. xfrm .-> xfrm_state #1 + |---. child .-> dst -. xfrm .-> xfrm_state #2 + |---. child .-> dst -. xfrm .-> xfrm_state #3 + |---. child .-> NULL + + Bundles are cached at xrfm_policy struct (field ->bundles). + + + Resolution of xrfm_tmpl + ----------------------- + Template contains: + 1. ->mode Mode: transport or tunnel + 2. ->id.proto Protocol: AH/ESP/IPCOMP + 3. ->id.daddr Remote tunnel endpoint, ignored for transport mode. + Q: allow to resolve security gateway? + 4. ->id.spi If not zero, static SPI. + 5. ->saddr Local tunnel endpoint, ignored for transport mode. + 6. ->algos List of allowed algos. Plain bitmask now. + Q: ealgos, aalgos, calgos. What a mess... + 7. ->share Sharing mode. + Q: how to implement private sharing mode? To add struct sock* to + flow id? + + Having this template we search through SAD searching for entries + with appropriate mode/proto/algo, permitted by selector. + If no appropriate entry found, it is requested from key manager. + + PROBLEMS: + Q: How to find all the bundles referring to a physical path for + PMTU discovery? Seems, dst should contain list of all parents... + and enter to infinite locking hierarchy disaster. + No! It is easier, we will not search for them, let them find us. + We add genid to each dst plus pointer to genid of raw IP route, + pmtu disc will update pmtu on raw IP route and increase its genid. + dst_check() will see this for top level and trigger resyncing + metrics. Plus, it will be made via sk->dst_cache. Solved. + */ + +/* Full description of state of transformer. */ +struct xfrm_state +{ + /* Note: bydst is re-used during gc */ + struct list_head bydst; + struct list_head byspi; + + atomic_t refcnt; + spinlock_t lock; + + struct xfrm_id id; + struct xfrm_selector sel; + + /* Key manger bits */ + struct { + u8 state; + u8 dying; + u32 seq; + } km; + + /* Parameters of this state. */ + struct { + u8 mode; + u8 replay_window; + u8 aalgo, ealgo, calgo; + u16 reqid; + u16 family; + xfrm_address_t saddr; + int header_len; + int trailer_len; + } props; + + struct xfrm_lifetime_cfg lft; + + /* Data for transformer */ + struct xfrm_algo *aalg; + struct xfrm_algo *ealg; + struct xfrm_algo *calg; + + /* Data for encapsulator */ + struct xfrm_encap_tmpl *encap; + + /* State for replay detection */ + struct xfrm_replay_state replay; + + /* Statistics */ + struct xfrm_stats stats; + + struct xfrm_lifetime_cur curlft; + struct timer_list timer; + + /* Reference to data common to all the instances of this + * transformer. */ + struct xfrm_type *type; + + /* Private data of this transformer, format is opaque, + * interpreted by xfrm_type methods. */ + void *data; +}; + +enum { + XFRM_STATE_VOID, + XFRM_STATE_ACQ, + XFRM_STATE_VALID, + XFRM_STATE_ERROR, + XFRM_STATE_EXPIRED, + XFRM_STATE_DEAD +}; + +struct xfrm_type; +struct xfrm_dst; +struct xfrm_policy_afinfo { + unsigned short family; + rwlock_t lock; + struct xfrm_type_map *type_map; + struct dst_ops *dst_ops; + void (*garbage_collect)(void); + int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl); + struct dst_entry *(*find_bundle)(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy); + int (*bundle_create)(struct xfrm_policy *policy, + struct xfrm_state **xfrm, + int nx, + struct flowi *fl, + struct dst_entry **dst_p); + void (*decode_session)(struct sk_buff *skb, + struct flowi *fl); +}; + +extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); +extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); +extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); +extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); + +#define XFRM_ACQ_EXPIRES 30 + +struct xfrm_tmpl; +struct xfrm_state_afinfo { + unsigned short family; + rwlock_t lock; + struct list_head *state_bydst; + struct list_head *state_byspi; + void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, + struct xfrm_tmpl *tmpl, + xfrm_address_t *daddr, xfrm_address_t *saddr); + struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); + struct xfrm_state *(*find_acq)(u8 mode, u16 reqid, u8 proto, + xfrm_address_t *daddr, xfrm_address_t *saddr, + int create); +}; + +extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); +extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); +extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); +extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); + +struct xfrm_decap_state; +struct xfrm_type +{ + char *description; + struct module *owner; + __u8 proto; + + int (*init_state)(struct xfrm_state *x, void *args); + void (*destructor)(struct xfrm_state *); + int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); + int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); + int (*output)(struct sk_buff *skb); + /* Estimate maximal size of result of transformation of a dgram */ + u32 (*get_max_size)(struct xfrm_state *, int size); +}; + +struct xfrm_type_map { + rwlock_t lock; + struct xfrm_type *map[256]; +}; + +extern int xfrm_register_type(struct xfrm_type *type, unsigned short family); +extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family); +extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family); +extern void xfrm_put_type(struct xfrm_type *type); + +struct xfrm_tmpl +{ +/* id in template is interpreted as: + * daddr - destination of tunnel, may be zero for transport mode. + * spi - zero to acquire spi. Not zero if spi is static, then + * daddr must be fixed too. + * proto - AH/ESP/IPCOMP + */ + struct xfrm_id id; + +/* Source address of tunnel. Ignored, if it is not a tunnel. */ + xfrm_address_t saddr; + + __u16 reqid; + +/* Mode: transport/tunnel */ + __u8 mode; + +/* Sharing mode: unique, this session only, this user only etc. */ + __u8 share; + +/* May skip this transfomration if no SA is found */ + __u8 optional; + +/* Bit mask of algos allowed for acquisition */ + __u32 aalgos; + __u32 ealgos; + __u32 calgos; +}; + +#define XFRM_MAX_DEPTH 4 + +struct xfrm_policy +{ + struct xfrm_policy *next; + + /* This lock only affects elements except for entry. */ + rwlock_t lock; + atomic_t refcnt; + struct timer_list timer; + + u32 priority; + u32 index; + struct xfrm_selector selector; + struct xfrm_lifetime_cfg lft; + struct xfrm_lifetime_cur curlft; + struct dst_entry *bundles; + __u16 family; + __u8 action; + __u8 flags; + __u8 dead; + __u8 xfrm_nr; + struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; +}; + +struct xfrm_mgr +{ + struct list_head list; + char *id; + int (*notify)(struct xfrm_state *x, int event); + int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); + struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); + int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); +}; + +extern int xfrm_register_km(struct xfrm_mgr *km); +extern int xfrm_unregister_km(struct xfrm_mgr *km); + + +#define XFRM_FLOWCACHE_HASH_SIZE 1024 + +static inline u32 __flow_hash4(struct flowi *fl) +{ + u32 hash = fl->fl4_src ^ fl->fl_ip_sport; + + hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); + + hash ^= fl->fl4_dst ^ fl->fl_ip_dport; + hash ^= (hash >> 10); + hash ^= (hash >> 20); + return hash & (XFRM_FLOWCACHE_HASH_SIZE-1); +} + +static inline u32 __flow_hash6(struct flowi *fl) +{ + u32 hash = fl->fl6_src->s6_addr32[2] ^ + fl->fl6_src->s6_addr32[3] ^ + fl->fl_ip_sport; + + hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); + + hash ^= fl->fl6_dst->s6_addr32[2] ^ + fl->fl6_dst->s6_addr32[3] ^ + fl->fl_ip_dport; + hash ^= (hash >> 10); + hash ^= (hash >> 20); + return hash & (XFRM_FLOWCACHE_HASH_SIZE-1); +} + +static inline u32 flow_hash(struct flowi *fl, unsigned short family) +{ + switch (family) { + case AF_INET: + return __flow_hash4(fl); + case AF_INET6: + return __flow_hash6(fl); + } + return 0; /*XXX*/ +} + +extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; + +static inline void xfrm_pol_hold(struct xfrm_policy *policy) +{ + if (policy) + atomic_inc(&policy->refcnt); +} + +extern void __xfrm_policy_destroy(struct xfrm_policy *policy); + +static inline void xfrm_pol_put(struct xfrm_policy *policy) +{ + if (atomic_dec_and_test(&policy->refcnt)) + __xfrm_policy_destroy(policy); +} + +#define XFRM_DST_HSIZE 1024 + +static __inline__ +unsigned __xfrm4_dst_hash(xfrm_address_t *addr) +{ + unsigned h; + h = ntohl(addr->a4); + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned __xfrm6_dst_hash(xfrm_address_t *addr) +{ + unsigned h; + h = ntohl(addr->a6[2]^addr->a6[3]); + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_dst_hash(addr); + case AF_INET6: + return __xfrm6_dst_hash(addr); + } + return 0; +} + +static __inline__ +unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) +{ + unsigned h; + h = ntohl(addr->a4^spi^proto); + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) +{ + unsigned h; + h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_spi_hash(addr, spi, proto); + case AF_INET6: + return __xfrm6_spi_hash(addr, spi, proto); + } + return 0; /*XXX*/ +} + +extern void __xfrm_state_destroy(struct xfrm_state *); + +static inline void xfrm_state_put(struct xfrm_state *x) +{ + if (atomic_dec_and_test(&x->refcnt)) + __xfrm_state_destroy(x); +} + +static inline void xfrm_state_hold(struct xfrm_state *x) +{ + atomic_inc(&x->refcnt); +} + +static __inline__ int addr_match(void *token1, void *token2, int prefixlen) +{ + __u32 *a1 = token1; + __u32 *a2 = token2; + int pdw; + int pbi; + + pdw = prefixlen >> 5; /* num of whole __u32 in prefix */ + pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */ + + if (pdw) + if (memcmp(a1, a2, pdw << 2)) + return 0; + + if (pbi) { + __u32 mask; + + mask = htonl((0xffffffff) << (32 - pbi)); + + if ((a1[pdw] ^ a2[pdw]) & mask) + return 0; + } + + return 1; +} + +static inline int +__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) +{ + return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && + addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && + !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) && + !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) && + (fl->proto == sel->proto || !sel->proto) && + (fl->oif == sel->ifindex || !sel->ifindex); +} + +static inline int +__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) +{ + return addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && + addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) && + !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) && + !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) && + (fl->proto == sel->proto || !sel->proto) && + (fl->oif == sel->ifindex || !sel->ifindex); +} + +static inline int +xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, + unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_selector_match(sel, fl); + case AF_INET6: + return __xfrm6_selector_match(sel, fl); + } + return 0; +} + +/* A struct encoding bundle of transformations to apply to some set of flow. + * + * dst->child points to the next element of bundle. + * dst->xfrm points to an instanse of transformer. + * + * Due to unfortunate limitations of current routing cache, which we + * have no time to fix, it mirrors struct rtable and bound to the same + * routing key, including saddr,daddr. However, we can have many of + * bundles differing by session id. All the bundles grow from a parent + * policy rule. + */ +struct xfrm_dst +{ + union { + struct xfrm_dst *next; + struct dst_entry dst; + struct rtable rt; + struct rt6_info rt6; + } u; +}; + +/* Decapsulation state, used by the input to store data during + * decapsulation procedure, to be used later (during the policy + * check + */ +struct xfrm_decap_state { + char decap_data[20]; + __u16 decap_type; +}; + +struct sec_decap_state { + struct xfrm_state *xvec; + struct xfrm_decap_state decap; +}; + +struct sec_path +{ + kmem_cache_t *pool; + atomic_t refcnt; + int len; + struct sec_decap_state x[XFRM_MAX_DEPTH]; +}; + +static inline struct sec_path * +secpath_get(struct sec_path *sp) +{ + if (sp) + atomic_inc(&sp->refcnt); + return sp; +} + +extern void __secpath_destroy(struct sec_path *sp); + +static inline void +secpath_put(struct sec_path *sp) +{ + if (sp && atomic_dec_and_test(&sp->refcnt)) + __secpath_destroy(sp); +} + +static inline int +__xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) +{ + return (tmpl->saddr.a4 && + tmpl->saddr.a4 != x->props.saddr.a4); +} + +static inline int +__xfrm6_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) +{ + return (!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) && + ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr)); +} + +static inline int +xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_state_addr_cmp(tmpl, x); + case AF_INET6: + return __xfrm6_state_addr_cmp(tmpl, x); + } + return !0; +} + +extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family); + +static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) +{ + if (sk && sk->policy[XFRM_POLICY_IN]) + return __xfrm_policy_check(sk, dir, skb, family); + + return !xfrm_policy_list[dir] || + (skb->dst->flags & DST_NOPOLICY) || + __xfrm_policy_check(sk, dir, skb, family); +} + +static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +{ + return xfrm_policy_check(sk, dir, skb, AF_INET); +} + +static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +{ + return xfrm_policy_check(sk, dir, skb, AF_INET6); +} + + +extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); + +static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) +{ + return !xfrm_policy_list[XFRM_POLICY_OUT] || + (skb->dst->flags & DST_NOXFRM) || + __xfrm_route_forward(skb, family); +} + +static inline int xfrm4_route_forward(struct sk_buff *skb) +{ + return xfrm_route_forward(skb, AF_INET); +} + +static inline int xfrm6_route_forward(struct sk_buff *skb) +{ + return xfrm_route_forward(skb, AF_INET6); +} + +extern int __xfrm_sk_clone_policy(struct sock *sk); + +static inline int xfrm_sk_clone_policy(struct sock *sk) +{ + if (unlikely(sk->policy[0] || sk->policy[1])) + return __xfrm_sk_clone_policy(sk); + return 0; +} + +extern void __xfrm_sk_free_policy(struct xfrm_policy *, int dir); + +static inline void xfrm_sk_free_policy(struct sock *sk) +{ + if (unlikely(sk->policy[0] != NULL)) { + __xfrm_sk_free_policy(sk->policy[0], 0); + sk->policy[0] = NULL; + } + if (unlikely(sk->policy[1] != NULL)) { + __xfrm_sk_free_policy(sk->policy[1], 1); + sk->policy[1] = NULL; + } +} + +static __inline__ +xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family) +{ + switch (family){ + case AF_INET: + return (xfrm_address_t *)&fl->fl4_dst; + case AF_INET6: + return (xfrm_address_t *)fl->fl6_dst; + } + return NULL; +} + +static __inline__ +xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family) +{ + switch (family){ + case AF_INET: + return (xfrm_address_t *)&fl->fl4_src; + case AF_INET6: + return (xfrm_address_t *)fl->fl6_src; + } + return NULL; +} + +static __inline__ int +__xfrm4_state_addr_check(struct xfrm_state *x, + xfrm_address_t *daddr, xfrm_address_t *saddr) +{ + if (daddr->a4 == x->id.daddr.a4 && + (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4)) + return 1; + return 0; +} + +static __inline__ int +__xfrm6_state_addr_check(struct xfrm_state *x, + xfrm_address_t *daddr, xfrm_address_t *saddr) +{ + if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) && + (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)|| + ipv6_addr_any((struct in6_addr *)saddr) || + ipv6_addr_any((struct in6_addr *)&x->props.saddr))) + return 1; + return 0; +} + +static __inline__ int +xfrm_state_addr_check(struct xfrm_state *x, + xfrm_address_t *daddr, xfrm_address_t *saddr, + unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_state_addr_check(x, daddr, saddr); + case AF_INET6: + return __xfrm6_state_addr_check(x, daddr, saddr); + } + return 0; +} + +/* + * xfrm algorithm information + */ +struct xfrm_algo_auth_info { + u16 icv_truncbits; + u16 icv_fullbits; +}; + +struct xfrm_algo_encr_info { + u16 blockbits; + u16 defkeybits; +}; + +struct xfrm_algo_comp_info { + u16 threshold; +}; + +struct xfrm_algo_desc { + char *name; + u8 available:1; + union { + struct xfrm_algo_auth_info auth; + struct xfrm_algo_encr_info encr; + struct xfrm_algo_comp_info comp; + } uinfo; + struct sadb_alg desc; +}; + +/* XFRM tunnel handlers. */ +struct xfrm_tunnel { + int (*handler)(struct sk_buff *skb); + void (*err_handler)(struct sk_buff *skb, void *info); +}; + +extern void xfrm_init(void); +extern void xfrm4_init(void); +extern void xfrm4_fini(void); +extern void xfrm6_init(void); +extern void xfrm6_fini(void); +extern void xfrm_state_init(void); +extern void xfrm4_state_init(void); +extern void xfrm4_state_fini(void); +extern void xfrm6_state_init(void); +extern void xfrm6_state_fini(void); + +extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); +extern struct xfrm_state *xfrm_state_alloc(void); +extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, + struct flowi *fl, struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err, + unsigned short family); +extern int xfrm_state_check_expire(struct xfrm_state *x); +extern void xfrm_state_insert(struct xfrm_state *x); +extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb); +extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); +extern void xfrm_state_delete(struct xfrm_state *x); +extern void xfrm_state_flush(u8 proto); +extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); +extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); +extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl); +extern int xfrm4_rcv(struct sk_buff *skb); +extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); +extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); +extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); +extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); +extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir); +extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen); + +void xfrm_policy_init(void); +void xfrm4_policy_init(void); +void xfrm6_policy_init(void); +struct xfrm_policy *xfrm_policy_alloc(int gfp); +extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); +struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, unsigned short family); +int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); +struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel); +struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); +void xfrm_policy_flush(void); +u32 xfrm_get_acqseq(void); +void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); +struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, + xfrm_address_t *daddr, xfrm_address_t *saddr, + int create, unsigned short family); +extern void xfrm_policy_flush(void); +extern void xfrm_policy_kill(struct xfrm_policy *); +extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); +extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl); +extern int xfrm_flush_bundles(struct xfrm_state *x); +extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); + +extern wait_queue_head_t km_waitq; +extern void km_warn_expired(struct xfrm_state *x); +extern void km_expired(struct xfrm_state *x); +extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol); +extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); + +extern void xfrm4_input_init(void); +extern void xfrm6_input_init(void); +extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); + +extern void xfrm_probe_algs(void); +extern int xfrm_count_auth_supported(void); +extern int xfrm_count_enc_supported(void); +extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx); +extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx); +extern struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx); +extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id); +extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id); +extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id); +extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name); +extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name); +extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name); + +struct crypto_tfm; +typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); + +extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, + int offset, int len, icv_update_fn_t icv_update); + +#endif /* _NET_XFRM_H */ diff -Nru a/lib/Config.in b/lib/Config.in --- a/lib/Config.in Wed Apr 23 17:09:06 2003 +++ b/lib/Config.in Wed Apr 23 17:09:06 2003 @@ -9,12 +9,14 @@ # if [ "$CONFIG_CRAMFS" = "y" -o \ "$CONFIG_PPP_DEFLATE" = "y" -o \ + "$CONFIG_CRYPTO_DEFLATE" = "y" -o \ "$CONFIG_JFFS2_FS" = "y" -o \ "$CONFIG_ZISOFS_FS" = "y" ]; then define_tristate CONFIG_ZLIB_INFLATE y else if [ "$CONFIG_CRAMFS" = "m" -o \ "$CONFIG_PPP_DEFLATE" = "m" -o \ + "$CONFIG_CRYPTO_DEFLATE" = "m" -o \ "$CONFIG_JFFS2_FS" = "m" -o \ "$CONFIG_ZISOFS_FS" = "m" ]; then define_tristate CONFIG_ZLIB_INFLATE m @@ -24,10 +26,12 @@ fi if [ "$CONFIG_PPP_DEFLATE" = "y" -o \ + "$CONFIG_CRYPTO_DEFLATE" = "y" -o \ "$CONFIG_JFFS2_FS" = "y" ]; then define_tristate CONFIG_ZLIB_DEFLATE y else if [ "$CONFIG_PPP_DEFLATE" = "m" -o \ + "$CONFIG_CRYPTO_DEFLATE" = "m" -o \ "$CONFIG_JFFS2_FS" = "m" ]; then define_tristate CONFIG_ZLIB_DEFLATE m else diff -Nru a/net/Config.in b/net/Config.in --- a/net/Config.in Wed Apr 23 17:09:06 2003 +++ b/net/Config.in Wed Apr 23 17:09:06 2003 @@ -16,9 +16,11 @@ fi bool 'Socket Filtering' CONFIG_FILTER tristate 'Unix domain sockets' CONFIG_UNIX +tristate 'PF_KEY sockets' CONFIG_NET_KEY bool 'TCP/IP networking' CONFIG_INET if [ "$CONFIG_INET" = "y" ]; then source net/ipv4/Config.in + source net/xfrm/Config.in if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then # IPv6 as module will cause a CRASH if you try to unload it tristate ' The IPv6 protocol (EXPERIMENTAL)' CONFIG_IPV6 diff -Nru a/net/Makefile b/net/Makefile --- a/net/Makefile Wed Apr 23 17:09:06 2003 +++ b/net/Makefile Wed Apr 23 17:09:06 2003 @@ -7,15 +7,15 @@ O_TARGET := network.o -mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core xfrm export-objs := netsyms.o subdir-y := core ethernet -subdir-m := ipv4 # hum? +subdir-m := ipv4 xfrm # hum? subdir-$(CONFIG_NET) += 802 sched netlink -subdir-$(CONFIG_INET) += ipv4 +subdir-$(CONFIG_INET) += ipv4 xfrm subdir-$(CONFIG_NETFILTER) += ipv4/netfilter subdir-$(CONFIG_UNIX) += unix subdir-$(CONFIG_IPV6) += ipv6 @@ -28,6 +28,7 @@ subdir-$(CONFIG_KHTTPD) += khttpd subdir-$(CONFIG_PACKET) += packet +subdir-$(CONFIG_NET_KEY) += key subdir-$(CONFIG_NET_SCHED) += sched subdir-$(CONFIG_BRIDGE) += bridge subdir-$(CONFIG_IPX) += ipx diff -Nru a/net/atm/clip.c b/net/atm/clip.c --- a/net/atm/clip.c Wed Apr 23 17:09:06 2003 +++ b/net/atm/clip.c Wed Apr 23 17:09:06 2003 @@ -509,6 +509,7 @@ struct atmarp_entry *entry; int error; struct clip_vcc *clip_vcc; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; struct rtable *rt; if (vcc->push != clip_push) { @@ -525,7 +526,7 @@ unlink_clip_vcc(clip_vcc); return 0; } - error = ip_route_output(&rt,ip,0,1,0); + error = ip_route_output_key(&rt,&fl); if (error) return error; neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); ip_rt_put(rt); diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Wed Apr 23 17:09:06 2003 +++ b/net/core/dev.c Wed Apr 23 17:09:06 2003 @@ -912,6 +912,13 @@ return notifier_chain_register(&netdev_chain, nb); } +/* Synchronize with packet receive processing. */ +void synchronize_net(void) +{ + br_write_lock_bh(BR_NETPROTO_LOCK); + br_write_unlock_bh(BR_NETPROTO_LOCK); +} + /** * unregister_netdevice_notifier - unregister a network notifier block * @nb: notifier diff -Nru a/net/core/dst.c b/net/core/dst.c --- a/net/core/dst.c Wed Apr 23 17:09:06 2003 +++ b/net/core/dst.c Wed Apr 23 17:09:06 2003 @@ -36,11 +36,11 @@ static unsigned long dst_gc_timer_expires; static unsigned long dst_gc_timer_inc = DST_GC_MAX; static void dst_run_gc(unsigned long); +static void ___dst_free(struct dst_entry * dst); static struct timer_list dst_gc_timer = { data: DST_GC_MIN, function: dst_run_gc }; - static void dst_run_gc(unsigned long dummy) { int delayed = 0; @@ -61,7 +61,25 @@ continue; } *dstp = dst->next; - dst_destroy(dst); + + dst = dst_destroy(dst); + if (dst) { + /* NOHASH and still referenced. Unless it is already + * on gc list, invalidate it and add to gc list. + * + * Note: this is temporary. Actually, NOHASH dst's + * must be obsoleted when parent is obsoleted. + * But we do not have state "obsoleted, but + * referenced by parent", so it is right. + */ + if (dst->obsolete > 1) + continue; + + ___dst_free(dst); + dst->next = *dstp; + *dstp = dst; + dstp = &dst->next; + } } if (!dst_garbage_list) { dst_gc_timer_inc = DST_GC_MAX; @@ -107,6 +125,7 @@ memset(dst, 0, ops->entry_size); dst->ops = ops; dst->lastuse = jiffies; + dst->path = dst; dst->input = dst_discard; dst->output = dst_blackhole; #if RT_CACHE_DEBUG >= 2 @@ -116,10 +135,8 @@ return dst; } -void __dst_free(struct dst_entry * dst) +static void ___dst_free(struct dst_entry * dst) { - spin_lock_bh(&dst_lock); - /* The first case (dev==NULL) is required, when protocol module is unloaded. */ @@ -128,6 +145,12 @@ dst->output = dst_blackhole; } dst->obsolete = 2; +} + +void __dst_free(struct dst_entry * dst) +{ + spin_lock_bh(&dst_lock); + ___dst_free(dst); dst->next = dst_garbage_list; dst_garbage_list = dst; if (dst_gc_timer_inc > DST_GC_INC) { @@ -137,14 +160,19 @@ dst_gc_timer.expires = jiffies + dst_gc_timer_expires; add_timer(&dst_gc_timer); } - spin_unlock_bh(&dst_lock); } -void dst_destroy(struct dst_entry * dst) +struct dst_entry *dst_destroy(struct dst_entry * dst) { - struct neighbour *neigh = dst->neighbour; - struct hh_cache *hh = dst->hh; + struct dst_entry *child; + struct neighbour *neigh; + struct hh_cache *hh; + +again: + neigh = dst->neighbour; + hh = dst->hh; + child = dst->child; dst->hh = NULL; if (hh && atomic_dec_and_test(&hh->hh_refcnt)) @@ -165,6 +193,21 @@ atomic_dec(&dst_total); #endif kmem_cache_free(dst->ops->kmem_cachep, dst); + + dst = child; + if (dst) { + if (atomic_dec_and_test(&dst->__refcnt)) { + /* We were real parent of this dst, so kill child. */ + if (dst->flags&DST_NOHASH) + goto again; + } else { + /* Child is still referenced, return it for freeing. */ + if (dst->flags&DST_NOHASH) + return dst; + /* Child is still in his hash table */ + } + } + return NULL; } static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr) diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c --- a/net/core/netfilter.c Wed Apr 23 17:09:06 2003 +++ b/net/core/netfilter.c Wed Apr 23 17:09:06 2003 @@ -563,13 +563,15 @@ { struct iphdr *iph = (*pskb)->nh.iph; struct rtable *rt; - struct rt_key key = { dst:iph->daddr, - src:iph->saddr, - oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, - tos:RT_TOS(iph->tos)|RTO_CONN, + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->daddr, + .saddr = iph->saddr, + .tos = RT_TOS(iph->tos)|RTO_CONN, #ifdef CONFIG_IP_ROUTE_FWMARK - fwmark:(*pskb)->nfmark + .fwmark = (*pskb)->nfmark #endif + } }, + .oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, }; struct net_device *dev_src = NULL; int err; @@ -578,10 +580,10 @@ 0 or a local address; however some non-standard hacks like ipt_REJECT.c:send_reset() can cause packets with foreign saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */ - if(key.src && !(dev_src = ip_dev_find(key.src))) - key.src = 0; + if(fl.fl4_src && !(dev_src = ip_dev_find(fl.fl4_src))) + fl.fl4_src = 0; - if ((err=ip_route_output_key(&rt, &key)) != 0) { + if ((err=ip_route_output_key(&rt, &fl)) != 0) { printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n", NIPQUAD(iph->daddr), NIPQUAD(iph->saddr), (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, diff -Nru a/net/core/rtnetlink.c b/net/core/rtnetlink.c --- a/net/core/rtnetlink.c Wed Apr 23 17:09:06 2003 +++ b/net/core/rtnetlink.c Wed Apr 23 17:09:06 2003 @@ -128,7 +128,7 @@ return err; } -int rtnetlink_put_metrics(struct sk_buff *skb, unsigned *metrics) +int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) { struct rtattr *mx = (struct rtattr*)skb->tail; int i; @@ -136,7 +136,7 @@ RTA_PUT(skb, RTA_METRICS, 0, NULL); for (i=0; irta_len = skb->tail - (u8*)mx; if (mx->rta_len == RTA_LENGTH(0)) diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c --- a/net/core/skbuff.c Wed Apr 23 17:09:06 2003 +++ b/net/core/skbuff.c Wed Apr 23 17:09:06 2003 @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -201,6 +202,7 @@ /* Set up other state */ skb->len = 0; + skb->local_df = 0; skb->cloned = 0; skb->data_len = 0; @@ -232,6 +234,7 @@ skb->stamp.tv_sec=0; /* No idea about time */ skb->dev = NULL; skb->dst = NULL; + skb->sp = NULL; memset(skb->cb, 0, sizeof(skb->cb)); skb->pkt_type = PACKET_HOST; /* Default type */ skb->ip_summed = 0; @@ -316,6 +319,9 @@ } dst_release(skb->dst); +#ifdef CONFIG_INET + secpath_put(skb->sp); +#endif if(skb->destructor) { if (in_irq()) { printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n", @@ -367,10 +373,15 @@ C(mac); C(dst); dst_clone(n->dst); + C(sp); +#ifdef CONFIG_INET + secpath_get(n->sp); +#endif memcpy(n->cb, skb->cb, sizeof(skb->cb)); C(len); C(data_len); C(csum); + C(local_df); n->cloned = 1; C(pkt_type); C(ip_summed); @@ -420,11 +431,15 @@ new->priority=old->priority; new->protocol=old->protocol; new->dst=dst_clone(old->dst); +#ifdef CONFIG_INET + new->sp=secpath_get(old->sp); +#endif new->h.raw=old->h.raw+offset; new->nh.raw=old->nh.raw+offset; new->mac.raw=old->mac.raw+offset; memcpy(new->cb, old->cb, sizeof(old->cb)); atomic_set(&new->users, 1); + new->local_df=old->local_df; new->pkt_type=old->pkt_type; new->stamp=old->stamp; new->destructor = NULL; diff -Nru a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c --- a/net/decnet/dn_nsp_out.c Wed Apr 23 17:09:06 2003 +++ b/net/decnet/dn_nsp_out.c Wed Apr 23 17:09:06 2003 @@ -593,7 +593,7 @@ * associations. */ skb->dst = dst_clone(dst); - skb->dst->output(skb); + dst_output(skb); } diff -Nru a/net/decnet/dn_route.c b/net/decnet/dn_route.c --- a/net/decnet/dn_route.c Wed Apr 23 17:09:06 2003 +++ b/net/decnet/dn_route.c Wed Apr 23 17:09:06 2003 @@ -100,7 +100,6 @@ static int dn_dst_gc(void); static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); -static struct dst_entry *dn_dst_reroute(struct dst_entry *, struct sk_buff *skb);