Index: releng/10.1/UPDATING =================================================================== --- releng/10.1/UPDATING (revision 284294) +++ releng/10.1/UPDATING (revision 284295) @@ -1,2230 +1,2233 @@ Updating Information for FreeBSD current users This file is maintained and copyrighted by M. Warner Losh . See end of file for further details. For commonly done items, please see the COMMON ITEMS: section later in the file. These instructions assume that you basically know what you are doing. If not, then please consult the FreeBSD handbook: http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. NOTE: FreeBSD has switched from gcc to clang. If you have trouble bootstrapping from older versions of FreeBSD, try WITHOUT_CLANG to bootstrap to the tip of stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20150612: p12 FreeBSD-SA-15:10.openssl + Fix multiple vulnerabilities in OpenSSL. [SA-15:10] + 20150609: p11 FreeBSD-EN-15:06.file FreeBSD-EN-15:07.zfs Updated base system file(1) to 5.22 to address multiple denial of service issues. [EN-15:06] Improved reliability of ZFS when TRIM/UNMAP and/or L2ARC is used. [EN-15:07] 20150513: p10 FreeBSD-EN-15:04.freebsd-update FreeBSD-EN-15:05.ufs Fix bug with freebsd-update(8) that does not ensure the previous upgrade was completed. [EN-15:04] Fix deadlock on reboot with UFS tuned with SU+J. [EN-15:05] 20150407: p9 FreeBSD-SA-15:04.igmp [revised] FreeBSD-SA-15:07.ntp FreeBSD-SA-15:08.bsdinstall FreeBSD-SA-15:09.ipv6 Improved patch for SA-15:04.igmp. Fix multiple vulnerabilities of ntp. [SA-15:07] Fix bsdinstall(8) insecure default GELI keyfile permissions. [SA-15:08] Fix Denial of Service with IPv6 Router Advertisements. [SA-15:09] 20150320: p8 Fix patch for SA-15:06.openssl. 20150319: p7 FreeBSD-SA-15:06.openssl Fix multiple vulnerabilities in OpenSSL. [SA-15:06] 20150225: p6 FreeBSD-SA-15:04.igmp FreeBSD-EN-15:01.vt FreeBSD-EN-15:02.openssl FreeBSD-EN-15:03.freebsd-update Fix integer overflow in IGMP protocol. [SA-15:04] Fix vt(4) crash with improper ioctl parameters. [EN-15:01] Updated base system OpenSSL to 1.0.1l. [EN-15:02] Fix freebsd-update libraries update ordering issue. [EN-15:03] 20150127: p5 FreeBSD-SA-15:02.kmem FreeBSD-SA-15:03.sctp Fix SCTP SCTP_SS_VALUE kernel memory corruption and disclosure vulnerability. [SA-15:02] Fix SCTP stream reset vulnerability. [SA-15:03] 20150114: p4 FreeBSD-SA-15:01.openssl Fix multiple vulnerabilities in OpenSSL. [SA-15:01] 20141223: p3 FreeBSD-SA-14:31.ntp FreeBSD-EN-14:13.freebsd-update Fix multiple vulnerabilities in NTP suite. [SA-14:31] Fix directory deletion issue in freebsd-update. [EN-14:13] 20141217: p2 FreeBSD-SA-14:30.unbound Fix unbound remote denial of service vulnerability. 20141210: p1 FreeBSD-SA-14:27.stdio FreeBSD-SA-14:28.file Fix buffer overflow in stdio. [SA-14:27] Fix multiple vulnerabilities in file(1) and libmagic(3). [SA-14:28] 20140904: The ofwfb driver, used to provide a graphics console on PowerPC when using vt(4), no longer allows mmap() of all of physical memory. This will prevent Xorg on PowerPC with some ATI graphics cards from initializing properly unless x11-servers/xorg-server is updated to 1.12.4_8 or newer. 20140831: The libatf-c and libatf-c++ major versions were downgraded to 0 and 1 respectively to match the upstream numbers. They were out of sync because, when they were originally added to FreeBSD, the upstream versions were not respected. These libraries are private and not yet built by default, so renumbering them should be a non-issue. However, unclean source trees will yield broken test programs once the operator executes "make delete-old-libs" after a "make installworld". Additionally, the atf-sh binary was made private by moving it into /usr/libexec/. Already-built shell test programs will keep the path to the old binary so they will break after "make delete-old" is run. If you are using WITH_TESTS=yes (not the default), wipe the object tree and rebuild from scratch to prevent spurious test failures. This is only needed once: the misnumbered libraries and misplaced binaries have been added to OptionalObsoleteFiles.inc so they will be removed during a clean upgrade. 20140814: The ixgbe tunables now match their sysctl counterparts, for example: hw.ixgbe.enable_aim => hw.ix.enable_aim Anyone using ixgbe tunables should ensure they update /boot/loader.conf. 20140801: The NFSv4.1 server committed by r269398 changes the internal function call interfaces used between the NFS and krpc modules. As such, __FreeBSD_version was bumped. 20140729: The default unbound configuration has been modified to address issues with reverse lookups on networks that use private address ranges. If you use the local_unbound service, run "service local_unbound setup" as root to regenerate your configuration, then "service local_unbound reload" to load the new configuration. 20140717: It is no longer necessary to include the dwarf version in your DEBUG options in your kernel config file. The bug that required it to be placed in the config file has bene fixed. DEBUG should now just contain -g. The build system will automatically update things to do the right thing. 20140715: Several ABI breaking changes were merged to CTL and new iSCSI code. All CTL and iSCSI-related tools, such as ctladm, ctld, iscsid and iscsictl need to be rebuilt to work with a new kernel. 20140708: The WITHOUT_VT_SUPPORT kernel config knob has been renamed WITHOUT_VT. (The other _SUPPORT knobs have a consistent meaning which differs from the behaviour controlled by this knob.) 20140608: On i386 and amd64 systems, the onifconsole flag is now set by default in /etc/ttys for ttyu0. This causes ttyu0 to be automatically enabled as a login TTY if it is set in the bootloader as an active kernel console. No changes in behavior should result otherwise. To revert to the previous behavior, set ttyu0 to "off" in /etc/ttys. 20140512: Clang and llvm have been upgraded to 3.4.1 release. 20140321: Clang and llvm have been upgraded to 3.4 release. 20140306: If a Makefile in a tests/ directory was auto-generating a Kyuafile instead of providing an explicit one, this would prevent such Makefile from providing its own Kyuafile in the future during NO_CLEAN builds. This has been fixed in the Makefiles but manual intervention is needed to clean an objdir if you use NO_CLEAN: # find /usr/obj -name Kyuafile | xargs rm -f 20140303: OpenSSH will now ignore errors caused by kernel lacking of Capsicum capability mode support. Please note that enabling the feature in kernel is still highly recommended. 20140227: OpenSSH is now built with sandbox support, and will use sandbox as the default privilege separation method. This requires Capsicum capability mode support in kernel. 20140216: The nve(4) driver for NVIDIA nForce MCP Ethernet adapters has been deprecated and will not be part of FreeBSD 11.0 and later releases. If you use this driver, please consider switching to the nfe(4) driver instead. 20140120: 10.0-RELEASE. 20131216: The behavior of gss_pseudo_random() for the krb5 mechanism has changed, for applications requesting a longer random string than produced by the underlying enctype's pseudo-random() function. In particular, the random string produced from a session key of enctype aes256-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96 will be different at the 17th octet and later, after this change. The counter used in the PRF+ construction is now encoded as a big-endian integer in accordance with RFC 4402. __FreeBSD_version is bumped to 1000701. 20131108: The WITHOUT_ATF build knob has been removed and its functionality has been subsumed into the more generic WITHOUT_TESTS. If you were using the former to disable the build of the ATF libraries, you should change your settings to use the latter. 20131031: The default version of mtree is nmtree which is obtained from NetBSD. The output is generally the same, but may vary slightly. If you found you need identical output adding "-F freebsd9" to the command line should do the trick. For the time being, the old mtree is available as fmtree. 20131014: libbsdyml has been renamed to libyaml and moved to /usr/lib/private. This will break ports-mgmt/pkg. Rebuild the port, or upgrade to pkg 1.1.4_8 and verify bsdyml not linked in, before running "make delete-old-libs": # make -C /usr/ports/ports-mgmt/pkg build deinstall install clean or # pkg install pkg; ldd /usr/local/sbin/pkg | grep bsdyml 20131010: The rc.d/jail script has been updated to support jail(8) configuration file. The "jail__*" rc.conf(5) variables for per-jail configuration are automatically converted to /var/run/jail..conf before the jail(8) utility is invoked. This is transparently backward compatible. See below about some incompatibilities and rc.conf(5) manual page for more details. These variables are now deprecated in favor of jail(8) configuration file. One can use "rc.d/jail config " command to generate a jail(8) configuration file in /var/run/jail..conf without running the jail(8) utility. The default pathname of the configuration file is /etc/jail.conf and can be specified by using $jail_conf or $jail__conf variables. Please note that jail_devfs_ruleset accepts an integer at this moment. Please consider to rewrite the ruleset name with an integer. 20130930: BIND has been removed from the base system. If all you need is a local resolver, simply enable and start the local_unbound service instead. Otherwise, several versions of BIND are available in the ports tree. The dns/bind99 port is one example. With this change, nslookup(1) and dig(1) are no longer in the base system. Users should instead use host(1) and drill(1) which are in the base system. Alternatively, nslookup and dig can be obtained by installing the dns/bind-tools port. 20130916: With the addition of unbound(8), a new unbound user is now required during installworld. "mergemaster -p" can be used to add the user prior to installworld, as documented in the handbook. 20130911: OpenSSH is now built with DNSSEC support, and will by default silently trust signed SSHFP records. This can be controlled with the VerifyHostKeyDNS client configuration setting. DNSSEC support can be disabled entirely with the WITHOUT_LDNS option in src.conf. 20130906: The GNU Compiler Collection and C++ standard library (libstdc++) are no longer built by default on platforms where clang is the system compiler. You can enable them with the WITH_GCC and WITH_GNUCXX options in src.conf. 20130905: The PROCDESC kernel option is now part of the GENERIC kernel configuration and is required for the rwhod(8) to work. If you are using custom kernel configuration, you should include 'options PROCDESC'. 20130905: The API and ABI related to the Capsicum framework was modified in backward incompatible way. The userland libraries and programs have to be recompiled to work with the new kernel. This includes the following libraries and programs, but the whole buildworld is advised: libc, libprocstat, dhclient, tcpdump, hastd, hastctl, kdump, procstat, rwho, rwhod, uniq. 20130903: AES-NI intrinsic support has been added to gcc. The AES-NI module has been updated to use this support. A new gcc is required to build the aesni module on both i386 and amd64. 20130821: The PADLOCK_RNG and RDRAND_RNG kernel options are now devices. Thus "device padlock_rng" and "device rdrand_rng" should be used instead of "options PADLOCK_RNG" & "options RDRAND_RNG". 20130813: WITH_ICONV has been split into two feature sets. WITH_ICONV now enables just the iconv* functionality and is now on by default. WITH_LIBICONV_COMPAT enables the libiconv api and link time compatability. Set WITHOUT_ICONV to build the old way. If you have been using WITH_ICONV before, you will very likely need to turn on WITH_LIBICONV_COMPAT. 20130806: INVARIANTS option now enables DEBUG for code with OpenSolaris and Illumos origin, including ZFS. If you have INVARIANTS in your kernel configuration, then there is no need to set DEBUG or ZFS_DEBUG explicitly. DEBUG used to enable witness(9) tracking of OpenSolaris (mostly ZFS) locks if WITNESS option was set. Because that generated a lot of witness(9) reports and all of them were believed to be false positives, this is no longer done. New option OPENSOLARIS_WITNESS can be used to achieve the previous behavior. 20130806: Timer values in IPv6 data structures now use time_uptime instead of time_second. Although this is not a user-visible functional change, userland utilities which directly use them---ndp(8), rtadvd(8), and rtsold(8) in the base system---need to be updated to r253970 or later. 20130802: find -delete can now delete the pathnames given as arguments, instead of only files found below them or if the pathname did not contain any slashes. Formerly, the following error message would result: find: -delete: : relative path potentially not safe Deleting the pathnames given as arguments can be prevented without error messages using -mindepth 1 or by changing directory and passing "." as argument to find. This works in the old as well as the new version of find. 20130726: Behavior of devfs rules path matching has been changed. Pattern is now always matched against fully qualified devfs path and slash characters must be explicitly matched by slashes in pattern (FNM_PATHNAME). Rulesets involving devfs subdirectories must be reviewed. 20130716: The default ARM ABI has changed to the ARM EABI. The old ABI is incompatible with the ARM EABI and all programs and modules will need to be rebuilt to work with a new kernel. To keep using the old ABI ensure the WITHOUT_ARM_EABI knob is set. NOTE: Support for the old ABI will be removed in the future and users are advised to upgrade. 20130709: pkg_install has been disconnected from the build if you really need it you should add WITH_PKGTOOLS in your src.conf(5). 20130709: Most of network statistics structures were changed to be able keep 64-bits counters. Thus all tools, that work with networking statistics, must be rebuilt (netstat(1), bsnmpd(1), etc.) 20130629: Fix targets that run multiple make's to use && rather than ; so that subsequent steps depend on success of previous. NOTE: if building 'universe' with -j* on stable/8 or stable/9 it would be better to start the build using bmake, to avoid overloading the machine. 20130618: Fix a bug that allowed a tracing process (e.g. gdb) to write to a memory-mapped file in the traced process's address space even if neither the traced process nor the tracing process had write access to that file. 20130615: CVS has been removed from the base system. An exact copy of the code is available from the devel/cvs port. 20130613: Some people report the following error after the switch to bmake: make: illegal option -- J usage: make [-BPSXeiknpqrstv] [-C directory] [-D variable] ... *** [buildworld] Error code 2 this likely due to an old instance of make in ${MAKEPATH} (${MAKEOBJDIRPREFIX}${.CURDIR}/make.${MACHINE}) which src/Makefile will use that blindly, if it exists, so if you see the above error: rm -rf `make -V MAKEPATH` should resolve it. 20130516: Use bmake by default. Whereas before one could choose to build with bmake via -DWITH_BMAKE one must now use -DWITHOUT_BMAKE to use the old make. The goal is to remove these knobs for 10-RELEASE. It is worth noting that bmake (like gmake) treats the command line as the unit of failure, rather than statements within the command line. Thus '(cd some/where && dosomething)' is safer than 'cd some/where; dosomething'. The '()' allows consistent behavior in parallel build. 20130429: Fix a bug that allows NFS clients to issue READDIR on files. 20130426: The WITHOUT_IDEA option has been removed because the IDEA patent expired. 20130426: The sysctl which controls TRIM support under ZFS has been renamed from vfs.zfs.trim_disable -> vfs.zfs.trim.enabled and has been enabled by default. 20130425: The mergemaster command now uses the default MAKEOBJDIRPREFIX rather than creating it's own in the temporary directory in order allow access to bootstrapped versions of tools such as install and mtree. When upgrading from version of FreeBSD where the install command does not support -l, you will need to install a new mergemaster command if mergemaster -p is required. This can be accomplished with the command (cd src/usr.sbin/mergemaster && make install). 20130404: Legacy ATA stack, disabled and replaced by new CAM-based one since FreeBSD 9.0, completely removed from the sources. Kernel modules atadisk and atapi*, user-level tools atacontrol and burncd are removed. Kernel option `options ATA_CAM` is now permanently enabled and removed. 20130319: SOCK_CLOEXEC and SOCK_NONBLOCK flags have been added to socket(2) and socketpair(2). Software, in particular Kerberos, may automatically detect and use these during building. The resulting binaries will not work on older kernels. 20130308: CTL_DISABLE has also been added to the sparc64 GENERIC (for further information, see the respective 20130304 entry). 20130304: Recent commits to callout(9) changed the size of struct callout, so the KBI is probably heavily disturbed. Also, some functions in callout(9)/sleep(9)/sleepqueue(9)/condvar(9) KPIs were replaced by macros. Every kernel module using it won't load, so rebuild is requested. The ctl device has been re-enabled in GENERIC for i386 and amd64, but does not initialize by default (because of the new CTL_DISABLE option) to save memory. To re-enable it, remove the CTL_DISABLE option from the kernel config file or set kern.cam.ctl.disable=0 in /boot/loader.conf. 20130301: The ctl device has been disabled in GENERIC for i386 and amd64. This was done due to the extra memory being allocated at system initialisation time by the ctl driver which was only used if a CAM target device was created. This makes a FreeBSD system unusable on 128MB or less of RAM. 20130208: A new compression method (lz4) has been merged to -HEAD. Please refer to zpool-features(7) for more information. Please refer to the "ZFS notes" section of this file for information on upgrading boot ZFS pools. 20130129: A BSD-licensed patch(1) variant has been added and is installed as bsdpatch, being the GNU version the default patch. To inverse the logic and use the BSD-licensed one as default, while having the GNU version installed as gnupatch, rebuild and install world with the WITH_BSD_PATCH knob set. 20130121: Due to the use of the new -l option to install(1) during build and install, you must take care not to directly set the INSTALL make variable in your /etc/make.conf, /etc/src.conf, or on the command line. If you wish to use the -C flag for all installs you may be able to add INSTALL+=-C to /etc/make.conf or /etc/src.conf. 20130118: The install(1) option -M has changed meaning and now takes an argument that is a file or path to append logs to. In the unlikely event that -M was the last option on the command line and the command line contained at least two files and a target directory the first file will have logs appended to it. The -M option served little practical purpose in the last decade so its use is expected to be extremely rare. 20121223: After switching to Clang as the default compiler some users of ZFS on i386 systems started to experience stack overflow kernel panics. Please consider using 'options KSTACK_PAGES=4' in such configurations. 20121222: GEOM_LABEL now mangles label names read from file system metadata. Mangling affect labels containing spaces, non-printable characters, '%' or '"'. Device names in /etc/fstab and other places may need to be updated. 20121217: By default, only the 10 most recent kernel dumps will be saved. To restore the previous behaviour (no limit on the number of kernel dumps stored in the dump directory) add the following line to /etc/rc.conf: savecore_flags="" 20121201: With the addition of auditdistd(8), a new auditdistd user is now required during installworld. "mergemaster -p" can be used to add the user prior to installworld, as documented in the handbook. 20121117: The sin6_scope_id member variable in struct sockaddr_in6 is now filled by the kernel before passing the structure to the userland via sysctl or routing socket. This means the KAME-specific embedded scope id in sin6_addr.s6_addr[2] is always cleared in userland application. This behavior can be controlled by net.inet6.ip6.deembed_scopeid. __FreeBSD_version is bumped to 1000025. 20121105: On i386 and amd64 systems WITH_CLANG_IS_CC is now the default. This means that the world and kernel will be compiled with clang and that clang will be installed as /usr/bin/cc, /usr/bin/c++, and /usr/bin/cpp. To disable this behavior and revert to building with gcc, compile with WITHOUT_CLANG_IS_CC. Really old versions of current may need to bootstrap WITHOUT_CLANG first if the clang build fails (its compatibility window doesn't extend to the 9 stable branch point). 20121102: The IPFIREWALL_FORWARD kernel option has been removed. Its functionality now turned on by default. 20121023: The ZERO_COPY_SOCKET kernel option has been removed and split into SOCKET_SEND_COW and SOCKET_RECV_PFLIP. NB: SOCKET_SEND_COW uses the VM page based copy-on-write mechanism which is not safe and may result in kernel crashes. NB: The SOCKET_RECV_PFLIP mechanism is useless as no current driver supports disposeable external page sized mbuf storage. Proper replacements for both zero-copy mechanisms are under consideration and will eventually lead to complete removal of the two kernel options. 20121023: The IPv4 network stack has been converted to network byte order. The following modules need to be recompiled together with kernel: carp(4), divert(4), gif(4), siftr(4), gre(4), pf(4), ipfw(4), ng_ipfw(4), stf(4). 20121022: Support for non-MPSAFE filesystems was removed from VFS. The VFS_VERSION was bumped, all filesystem modules shall be recompiled. 20121018: All the non-MPSAFE filesystems have been disconnected from the build. The full list includes: codafs, hpfs, ntfs, nwfs, portalfs, smbfs, xfs. 20121016: The interface cloning API and ABI has changed. The following modules need to be recompiled together with kernel: ipfw(4), pfsync(4), pflog(4), usb(4), wlan(4), stf(4), vlan(4), disc(4), edsc(4), if_bridge(4), gif(4), tap(4), faith(4), epair(4), enc(4), tun(4), if_lagg(4), gre(4). 20121015: The sdhci driver was split in two parts: sdhci (generic SD Host Controller logic) and sdhci_pci (actual hardware driver). No kernel config modifications are required, but if you load sdhc as a module you must switch to sdhci_pci instead. 20121014: Import the FUSE kernel and userland support into base system. 20121013: The GNU sort(1) program has been removed since the BSD-licensed sort(1) has been the default for quite some time and no serious problems have been reported. The corresponding WITH_GNU_SORT knob has also gone. 20121006: The pfil(9) API/ABI for AF_INET family has been changed. Packet filtering modules: pf(4), ipfw(4), ipfilter(4) need to be recompiled with new kernel. 20121001: The net80211(4) ABI has been changed to allow for improved driver PS-POLL and power-save support. All wireless drivers need to be recompiled to work with the new kernel. 20120913: The random(4) support for the VIA hardware random number generator (`PADLOCK') is no longer enabled unconditionally. Add the padlock_rng device in the custom kernel config if needed. The GENERIC kernels on i386 and amd64 do include the device, so the change only affects the custom kernel configurations. 20120908: The pf(4) packet filter ABI has been changed. pfctl(8) and snmp_pf module need to be recompiled to work with new kernel. 20120828: A new ZFS feature flag "com.delphix:empty_bpobj" has been merged to -HEAD. Pools that have empty_bpobj in active state can not be imported read-write with ZFS implementations that do not support this feature. For more information read the zpool-features(5) manual page. 20120727: The sparc64 ZFS loader has been changed to no longer try to auto- detect ZFS providers based on diskN aliases but now requires these to be explicitly listed in the OFW boot-device environment variable. 20120712: The OpenSSL has been upgraded to 1.0.1c. Any binaries requiring libcrypto.so.6 or libssl.so.6 must be recompiled. Also, there are configuration changes. Make sure to merge /etc/ssl/openssl.cnf. 20120712: The following sysctls and tunables have been renamed for consistency with other variables: kern.cam.da.da_send_ordered -> kern.cam.da.send_ordered kern.cam.ada.ada_send_ordered -> kern.cam.ada.send_ordered 20120628: The sort utility has been replaced with BSD sort. For now, GNU sort is also available as "gnusort" or the default can be set back to GNU sort by setting WITH_GNU_SORT. In this case, BSD sort will be installed as "bsdsort". 20120611: A new version of ZFS (pool version 5000) has been merged to -HEAD. Starting with this version the old system of ZFS pool versioning is superseded by "feature flags". This concept enables forward compatibility against certain future changes in functionality of ZFS pools. The first read-only compatible "feature flag" for ZFS pools is named "com.delphix:async_destroy". For more information read the new zpool-features(5) manual page. Please refer to the "ZFS notes" section of this file for information on upgrading boot ZFS pools. 20120417: The malloc(3) implementation embedded in libc now uses sources imported as contrib/jemalloc. The most disruptive API change is to /etc/malloc.conf. If your system has an old-style /etc/malloc.conf, delete it prior to installworld, and optionally re-create it using the new format after rebooting. See malloc.conf(5) for details (specifically the TUNING section and the "opt.*" entries in the MALLCTL NAMESPACE section). 20120328: Big-endian MIPS TARGET_ARCH values no longer end in "eb". mips64eb is now spelled mips64. mipsn32eb is now spelled mipsn32. mipseb is now spelled mips. This is to aid compatibility with third-party software that expects this naming scheme in uname(3). Little-endian settings are unchanged. If you are updating a big-endian mips64 machine from before this change, you may need to set MACHINE_ARCH=mips64 in your environment before the new build system will recognize your machine. 20120306: Disable by default the option VFS_ALLOW_NONMPSAFE for all supported platforms. 20120229: Now unix domain sockets behave "as expected" on nullfs(5). Previously nullfs(5) did not pass through all behaviours to the underlying layer, as a result if we bound to a socket on the lower layer we could connect only to the lower path; if we bound to the upper layer we could connect only to the upper path. The new behavior is one can connect to both the lower and the upper paths regardless what layer path one binds to. 20120211: The getifaddrs upgrade path broken with 20111215 has been restored. If you have upgraded in between 20111215 and 20120209 you need to recompile libc again with your kernel. You still need to recompile world to be able to configure CARP but this restriction already comes from 20111215. 20120114: The set_rcvar() function has been removed from /etc/rc.subr. All base and ports rc.d scripts have been updated, so if you have a port installed with a script in /usr/local/etc/rc.d you can either hand-edit the rcvar= line, or reinstall the port. An easy way to handle the mass-update of /etc/rc.d: rm /etc/rc.d/* && mergemaster -i 20120109: panic(9) now stops other CPUs in the SMP systems, disables interrupts on the current CPU and prevents other threads from running. This behavior can be reverted using the kern.stop_scheduler_on_panic tunable/sysctl. The new behavior can be incompatible with kern.sync_on_panic. 20111215: The carp(4) facility has been changed significantly. Configuration of the CARP protocol via ifconfig(8) has changed, as well as format of CARP events submitted to devd(8) has changed. See manual pages for more information. The arpbalance feature of carp(4) is currently not supported anymore. Size of struct in_aliasreq, struct in6_aliasreq has changed. User utilities using SIOCAIFADDR, SIOCAIFADDR_IN6, e.g. ifconfig(8), need to be recompiled. 20111122: The acpi_wmi(4) status device /dev/wmistat has been renamed to /dev/wmistat0. 20111108: The option VFS_ALLOW_NONMPSAFE option has been added in order to explicitely support non-MPSAFE filesystems. It is on by default for all supported platform at this present time. 20111101: The broken amd(4) driver has been replaced with esp(4) in the amd64, i386 and pc98 GENERIC kernel configuration files. 20110930: sysinstall has been removed 20110923: The stable/9 branch created in subversion. This corresponds to the RELENG_9 branch in CVS. 20110913: This commit modifies vfs_register() so that it uses a hash calculation to set vfc_typenum, which is enabled by default. The first time a system is booted after this change, the vfc_typenum values will change for all file systems. The main effect of this is a change to the NFS server file handles for file systems that use vfc_typenum in their fsid, such as ZFS. It will, however, prevent vfc_typenum from changing when file systems are loaded in a different order for subsequent reboots. To disable this, you can set vfs.typenumhash=0 in /boot/loader.conf until you are ready to remount all NFS clients after a reboot. 20110828: Bump the shared library version numbers for libraries that do not use symbol versioning, have changed the ABI compared to stable/8 and which shared library version was not bumped. Done as part of 9.0-RELEASE cycle. 20110815: During the merge of Capsicum features, the fget(9) KPI was modified. This may require the rebuilding of out-of-tree device drivers -- issues have been reported specifically with the nVidia device driver. __FreeBSD_version is bumped to 900041. Also, there is a period between 20110811 and 20110814 where the special devices /dev/{stdin,stdout,stderr} did not work correctly. Building world from a kernel during that window may not work. 20110628: The packet filter (pf) code has been updated to OpenBSD 4.5. You need to update userland tools to be in sync with kernel. This update breaks backward compatibility with earlier pfsync(4) versions. Care must be taken when updating redundant firewall setups. 20110608: The following sysctls and tunables are retired on x86 platforms: machdep.hlt_cpus machdep.hlt_logical_cpus The following sysctl is retired: machdep.hyperthreading_allowed The sysctls were supposed to provide a way to dynamically offline and online selected CPUs on x86 platforms, but the implementation has not been reliable especially with SCHED_ULE scheduler. machdep.hyperthreading_allowed tunable is still available to ignore hyperthreading CPUs at OS level. Individual CPUs can be disabled using hint.lapic.X.disabled tunable, where X is an APIC ID of a CPU. Be advised, though, that disabling CPUs in non-uniform fashion will result in non-uniform topology and may lead to sub-optimal system performance with SCHED_ULE, which is a default scheduler. 20110607: cpumask_t type is retired and cpuset_t is used in order to describe a mask of CPUs. 20110531: Changes to ifconfig(8) for dynamic address family detection mandate that you are running a kernel of 20110525 or later. Make sure to follow the update procedure to boot a new kernel before installing world. 20110513: Support for sun4v architecture is officially dropped 20110503: Several KPI breaking changes have been committed to the mii(4) layer, the PHY drivers and consequently some Ethernet drivers using mii(4). This means that miibus.ko and the modules of the affected Ethernet drivers need to be recompiled. Note to kernel developers: Given that the OUI bit reversion problem was fixed as part of these changes all mii(4) commits related to OUIs, i.e. to sys/dev/mii/miidevs, PHY driver probing and vendor specific handling, no longer can be merged verbatim to stable/8 and previous branches. 20110430: Users of the Atheros AR71xx SoC code now need to add 'device ar71xx_pci' into their kernel configurations along with 'device pci'. 20110427: The default NFS client is now the new NFS client, so fstype "newnfs" is now "nfs" and the regular/old NFS client is now fstype "oldnfs". Although mounts via fstype "nfs" will usually work without userland changes, it is recommended that the mount(8) and mount_nfs(8) commands be rebuilt from sources and that a link to mount_nfs called mount_oldnfs be created. The new client is compiled into the kernel with "options NFSCL" and this is needed for diskless root file systems. The GENERIC kernel configs have been changed to use NFSCL and NFSD (the new server) instead of NFSCLIENT and NFSSERVER. To use the regular/old client, you can "mount -t oldnfs ...". For a diskless root file system, you must also include a line like: vfs.root.mountfrom="oldnfs:" in the boot/loader.conf on the root fs on the NFS server to make a diskless root fs use the old client. 20110424: The GENERIC kernels for all architectures now default to the new CAM-based ATA stack. It means that all legacy ATA drivers were removed and replaced by respective CAM drivers. If you are using ATA device names in /etc/fstab or other places, make sure to update them respectively (adX -> adaY, acdX -> cdY, afdX -> daY, astX -> saY, where 'Y's are the sequential numbers starting from zero for each type in order of detection, unless configured otherwise with tunables, see cam(4)). There will be symbolic links created in /dev/ to map old adX devices to the respective adaY. They should provide basic compatibility for file systems mounting in most cases, but they do not support old user-level APIs and do not have respective providers in GEOM. Consider using updated management tools with new device names. It is possible to load devices ahci, ata, siis and mvs as modules, but option ATA_CAM should remain in kernel configuration to make ata module work as CAM driver supporting legacy ATA controllers. Device ata still can be used in modular fashion (atacore + ...). Modules atadisk and atapi* are not used and won't affect operation in ATA_CAM mode. Note that to use CAM-based ATA kernel should include CAM devices scbus, pass, da (or explicitly ada), cd and optionally others. All of them are parts of the cam module. ataraid(4) functionality is now supported by the RAID GEOM class. To use it you can load geom_raid kernel module and use graid(8) tool for management. Instead of /dev/arX device names, use /dev/raid/rX. No kernel config options or code have been removed, so if a problem arises, please report it and optionally revert to the old ATA stack. In order to do it you can remove from the kernel config: options ATA_CAM device ahci device mvs device siis , and instead add back: device atadisk # ATA disk drives device ataraid # ATA RAID drives device atapicd # ATAPI CDROM drives device atapifd # ATAPI floppy drives device atapist # ATAPI tape drives 20110423: The default NFS server has been changed to the new server, which was referred to as the experimental server. If you need to switch back to the old NFS server, you must now put the "-o" option on both the mountd and nfsd commands. This can be done using the mountd_flags and nfs_server_flags rc.conf variables until an update to the rc scripts is committed, which is coming soon. 20110418: The GNU Objective-C runtime library (libobjc), and other Objective-C related components have been removed from the base system. If you require an Objective-C library, please use one of the available ports. 20110331: ath(4) has been split into bus- and device- modules. if_ath contains the HAL, the TX rate control and the network device code. if_ath_pci contains the PCI bus glue. For Atheros MIPS embedded systems, if_ath_ahb contains the AHB glue. Users need to load both if_ath_pci and if_ath in order to use ath on everything else. TO REPEAT: if_ath_ahb is not needed for normal users. Normal users only need to load if_ath and if_ath_pci for ath(4) operation. 20110314: As part of the replacement of sysinstall, the process of building release media has changed significantly. For details, please re-read release(7), which has been updated to reflect the new build process. 20110218: GNU binutils 2.17.50 (as of 2007-07-03) has been merged to -HEAD. This is the last available version under GPLv2. It brings a number of new features, such as support for newer x86 CPU's (with SSE-3, SSSE-3, SSE 4.1 and SSE 4.2), better support for powerpc64, a number of new directives, and lots of other small improvements. See the ChangeLog file in contrib/binutils for the full details. 20110218: IPsec's HMAC_SHA256-512 support has been fixed to be RFC4868 compliant, and will now use half of hash for authentication. This will break interoperability with all stacks (including all actual FreeBSD versions) who implement draft-ietf-ipsec-ciph-sha-256-00 (they use 96 bits of hash for authentication). The only workaround with such peers is to use another HMAC algorithm for IPsec ("phase 2") authentication. 20110207: Remove the uio_yield prototype and symbol. This function has been misnamed since it was introduced and should not be globally exposed with this name. The equivalent functionality is now available using kern_yield(curthread->td_user_pri). The function remains undocumented. 20110112: A SYSCTL_[ADD_]UQUAD was added for unsigned uint64_t pointers, symmetric with the existing SYSCTL_[ADD_]QUAD. Type checking for scalar sysctls is defined but disabled. Code that needs UQUAD to pass the type checking that must compile on older systems where the define is not present can check against __FreeBSD_version >= 900030. The system dialog(1) has been replaced with a new version previously in ports as devel/cdialog. dialog(1) is mostly command-line compatible with the previous version, but the libdialog associated with it has a largely incompatible API. As such, the original version of libdialog will be kept temporarily as libodialog, until its base system consumers are replaced or updated. Bump __FreeBSD_version to 900030. 20110103: If you are trying to run make universe on a -stable system, and you get the following warning: "Makefile", line 356: "Target architecture for i386/conf/GENERIC unknown. config(8) likely too old." or something similar to it, then you must upgrade your -stable system to 8.2-Release or newer (really, any time after r210146 7/15/2010 in stable/8) or build the config from the latest stable/8 branch and install it on your system. Prior to this date, building a current universe on 8-stable system from between 7/15/2010 and 1/2/2011 would result in a weird shell parsing error in the first kernel build phase. A new config on those old systems will fix that problem for older versions of -current. 20101228: The TCP stack has been modified to allow Khelp modules to interact with it via helper hook points and store per-connection data in the TCP control block. Bump __FreeBSD_version to 900029. User space tools that rely on the size of struct tcpcb in tcp_var.h (e.g. sockstat) need to be recompiled. 20101114: Generic IEEE 802.3 annex 31B full duplex flow control support has been added to mii(4) and bge(4), bce(4), msk(4), nfe(4) and stge(4) along with brgphy(4), e1000phy(4) as well as ip1000phy() have been converted to take advantage of it instead of using custom implementations. This means that these drivers now no longer unconditionally advertise support for flow control but only do so if flow control is a selected media option. This was implemented in the generic support that way in order to allow flow control to be switched on and off via ifconfig(8) with the PHY specific default to typically off in order to protect from unwanted effects. Consequently, if you used flow control with one of the above mentioned drivers you now need to explicitly enable it, for example via: ifconfig bge0 media auto mediaopt flowcontrol Along with the above mentioned changes generic support for setting 1000baseT master mode also has been added and brgphy(4), ciphy(4), e1000phy(4) as well as ip1000phy(4) have been converted to take advantage of it. This means that these drivers now no longer take the link0 parameter for selecting master mode but the master media option has to be used instead, for example like in the following: ifconfig bge0 media 1000baseT mediaopt full-duplex,master Selection of master mode now is also available with all other PHY drivers supporting 1000baseT. 20101111: The TCP stack has received a significant update to add support for modularised congestion control and generally improve the clarity of congestion control decisions. Bump __FreeBSD_version to 900025. User space tools that rely on the size of struct tcpcb in tcp_var.h (e.g. sockstat) need to be recompiled. 20101002: The man(1) utility has been replaced by a new version that no longer uses /etc/manpath.config. Please consult man.conf(5) for how to migrate local entries to the new format. 20100928: The copyright strings printed by login(1) and sshd(8) at the time of a new connection have been removed to follow other operating systems and upstream sshd. 20100915: A workaround for a fixed ld bug has been removed in kernel code, so make sure that your system ld is built from sources after revision 210245 from 2010-07-19 (r211583 if building head kernel on stable/8, r211584 for stable/7; both from 2010-08-21). A symptom of incorrect ld version is different addresses for set_pcpu section and __start_set_pcpu symbol in kernel and/or modules. 20100913: The $ipv6_prefer variable in rc.conf(5) has been split into $ip6addrctl_policy and $ipv6_activate_all_interfaces. The $ip6addrctl_policy is a variable to choose a pre-defined address selection policy set by ip6addrctl(8). A value "ipv4_prefer", "ipv6_prefer" or "AUTO" can be specified. The default is "AUTO". The $ipv6_activate_all_interfaces specifies whether IFDISABLED flag (see an entry of 20090926) is set on an interface with no corresponding $ifconfig_IF_ipv6 line. The default is "NO" for security reason. If you want IPv6 link-local address on all interfaces by default, set this to "YES". The old ipv6_prefer="YES" is equivalent to ipv6_activate_all_interfaces="YES" and ip6addrctl_policy="ipv6_prefer". 20100913: DTrace has grown support for userland tracing. Due to this, DTrace is now i386 and amd64 only. dtruss(1) is now installed by default on those systems and a new kernel module is needed for userland tracing: fasttrap. No changes to your kernel config file are necessary to enable userland tracing, but you might consider adding 'STRIP=' and 'CFLAGS+=-fno-omit-frame-pointer' to your make.conf if you want to have informative userland stack traces in DTrace (ustack). 20100725: The acpi_aiboost(4) driver has been removed in favor of the new aibs(4) driver. You should update your kernel configuration file. 20100722: BSD grep has been imported to the base system and it is built by default. It is completely BSD licensed, highly GNU-compatible, uses less memory than its GNU counterpart and has a small codebase. However, it is slower than its GNU counterpart, which is mostly noticeable for larger searches, for smaller ones it is measurable but not significant. The reason is complex, the most important factor is that we lack a modern and efficient regex library and GNU overcomes this by optimizing the searches internally. Future work on improving the regex performance is planned, for the meantime, users that need better performance, can build GNU grep instead by setting the WITH_GNU_GREP knob. 20100713: Due to the import of powerpc64 support, all existing powerpc kernel configuration files must be updated with a machine directive like this: machine powerpc powerpc In addition, an updated config(8) is required to build powerpc kernels after this change. 20100713: A new version of ZFS (version 15) has been merged to -HEAD. This version uses a python library for the following subcommands: zfs allow, zfs unallow, zfs groupspace, zfs userspace. For full functionality of these commands the following port must be installed: sysutils/py-zfs 20100429: 'vm_page's are now hashed by physical address to an array of mutexes. Currently this is only used to serialize access to hold_count. Over time the page queue mutex will be peeled away. This changes the size of pmap on every architecture. And requires all callers of vm_page_hold and vm_page_unhold to be updated. 20100402: WITH_CTF can now be specified in src.conf (not recommended, there are some problems with static executables), make.conf (would also affect ports which do not use GNU make and do not override the compile targets) or in the kernel config (via "makeoptions WITH_CTF=yes"). When WITH_CTF was specified there before this was silently ignored, so make sure that WITH_CTF is not used in places which could lead to unwanted behavior. 20100311: The kernel option COMPAT_IA32 has been replaced with COMPAT_FREEBSD32 to allow 32-bit compatibility on non-x86 platforms. All kernel configurations on amd64 and ia64 platforms using these options must be modified accordingly. 20100113: The utmp user accounting database has been replaced with utmpx, the user accounting interface standardized by POSIX. Unfortunately the semantics of utmp and utmpx don't match, making it practically impossible to support both interfaces. The user accounting database is used by tools like finger(1), last(1), talk(1), w(1) and ac(8). All applications in the base system use utmpx. This means only local binaries (e.g. from the ports tree) may still use these utmp database files. These applications must be rebuilt to make use of utmpx. After the system has been upgraded, it is safe to remove the old log files (/var/run/utmp, /var/log/lastlog and /var/log/wtmp*), assuming their contents is of no importance anymore. Old wtmp databases can only be used by last(1) and ac(8) after they have been converted to the new format using wtmpcvt(1). 20100108: Introduce the kernel thread "deadlock resolver" (which can be enabled via the DEADLKRES option, see NOTES for more details) and the sleepq_type() function for sleepqueues. 20091202: The rc.firewall and rc.firewall6 were unified, and rc.firewall6 and rc.d/ip6fw were removed. According to the removal of rc.d/ip6fw, ipv6_firewall_* rc variables are obsoleted. Instead, the following new rc variables are added to rc.d/ipfw: firewall_client_net_ipv6, firewall_simple_iif_ipv6, firewall_simple_inet_ipv6, firewall_simple_oif_ipv6, firewall_simple_onet_ipv6, firewall_trusted_ipv6 The meanings correspond to the relevant IPv4 variables. 20091125: 8.0-RELEASE. 20091113: The default terminal emulation for syscons(4) has been changed from cons25 to xterm on all platforms except pc98. This means that the /etc/ttys file needs to be updated to ensure correct operation of applications on the console. The terminal emulation style can be toggled per window by using vidcontrol(1)'s -T flag. The TEKEN_CONS25 kernel configuration options can be used to change the compile-time default back to cons25. To prevent graphical artifacts, make sure the TERM environment variable is set to match the terminal emulation that is being performed by syscons(4). 20091109: The layout of the structure ieee80211req_scan_result has changed. Applications that require wireless scan results (e.g. ifconfig(8)) from net80211 need to be recompiled. Applications such as wpa_supplicant(8) may require a full world build without using NO_CLEAN in order to get synchronized with the new structure. 20091025: The iwn(4) driver has been updated to support the 5000 and 5150 series. There's one kernel module for each firmware. Adding "device iwnfw" to the kernel configuration file means including all three firmware images inside the kernel. If you want to include just the one for your wireless card, use the devices iwn4965fw, iwn5000fw or iwn5150fw. 20090926: The rc.d/network_ipv6, IPv6 configuration script has been integrated into rc.d/netif. The changes are the following: 1. To use IPv6, simply define $ifconfig_IF_ipv6 like $ifconfig_IF for IPv4. For aliases, $ifconfig_IF_aliasN should be used. Note that both variables need the "inet6" keyword at the head. Do not set $ipv6_network_interfaces manually if you do not understand what you are doing. It is not needed in most cases. $ipv6_ifconfig_IF and $ipv6_ifconfig_IF_aliasN still work, but they are obsolete. 2. $ipv6_enable is obsolete. Use $ipv6_prefer and "inet6 accept_rtadv" keyword in ifconfig(8) instead. If you define $ipv6_enable=YES, it means $ipv6_prefer=YES and all configured interfaces have "inet6 accept_rtadv" in the $ifconfig_IF_ipv6. These are for backward compatibility. 3. A new variable $ipv6_prefer has been added. If NO, IPv6 functionality of interfaces with no corresponding $ifconfig_IF_ipv6 is disabled by using "inet6 ifdisabled" flag, and the default address selection policy of ip6addrctl(8) is the IPv4-preferred one (see rc.d/ip6addrctl for more details). Note that if you want to configure IPv6 functionality on the disabled interfaces after boot, first you need to clear the flag by using ifconfig(8) like: ifconfig em0 inet6 -ifdisabled If YES, the default address selection policy is set as IPv6-preferred. The default value of $ipv6_prefer is NO. 4. If your system need to receive Router Advertisement messages, define "inet6 accept_rtadv" in $ifconfig_IF_ipv6. The rc(8) scripts automatically invoke rtsol(8) when the interface becomes UP. The Router Advertisement messages are used for SLAAC (State-Less Address AutoConfiguration). 20090922: 802.11s D3.03 support was committed. This is incompatible with the previous code, which was based on D3.0. 20090912: A sysctl variable net.inet6.ip6.accept_rtadv now sets the default value of a per-interface flag ND6_IFF_ACCEPT_RTADV, not a global knob to control whether accepting Router Advertisement messages or not. Also, a per-interface flag ND6_IFF_AUTO_LINKLOCAL has been added and a sysctl variable net.inet6.ip6.auto_linklocal is its default value. The ifconfig(8) utility now supports these flags. 20090910: ZFS snapshots are now mounted with MNT_IGNORE flag. Use -v option for mount(8) and -a option for df(1) to see them. 20090825: The old tunable hw.bus.devctl_disable has been superseded by hw.bus.devctl_queue. hw.bus.devctl_disable=1 in loader.conf should be replaced by hw.bus.devctl_queue=0. The default for this new tunable is 1000. 20090813: Remove the option STOP_NMI. The default action is now to use NMI only for KDB via the newly introduced function stop_cpus_hard() and maintain stop_cpus() to just use a normal IPI_STOP on ia32 and amd64. 20090803: The stable/8 branch created in subversion. This corresponds to the RELENG_8 branch in CVS. 20090719: Bump the shared library version numbers for all libraries that do not use symbol versioning as part of the 8.0-RELEASE cycle. Bump __FreeBSD_version to 800105. 20090714: Due to changes in the implementation of virtual network stack support, all network-related kernel modules must be recompiled. As this change breaks the ABI, bump __FreeBSD_version to 800104. 20090713: The TOE interface to the TCP syncache has been modified to remove struct tcpopt () from the ABI of the network stack. The cxgb driver is the only TOE consumer affected by this change, and needs to be recompiled along with the kernel. As this change breaks the ABI, bump __FreeBSD_version to 800103. 20090712: Padding has been added to struct tcpcb, sackhint and tcpstat in to facilitate future MFCs and bug fixes whilst maintaining the ABI. However, this change breaks the ABI, so bump __FreeBSD_version to 800102. User space tools that rely on the size of any of these structs (e.g. sockstat) need to be recompiled. 20090630: The NFS_LEGACYRPC option has been removed along with the old kernel RPC implementation that this option selected. Kernel configurations may need to be adjusted. 20090629: The network interface device nodes at /dev/net/ have been removed. All ioctl operations can be performed the normal way using routing sockets. The kqueue functionality can generally be replaced with routing sockets. 20090628: The documentation from the FreeBSD Documentation Project (Handbook, FAQ, etc.) is now installed via packages by sysinstall(8) and under the /usr/local/share/doc/freebsd directory instead of /usr/share/doc. 20090624: The ABI of various structures related to the SYSV IPC API have been changed. As a result, the COMPAT_FREEBSD[456] and COMPAT_43 kernel options now all require COMPAT_FREEBSD7. Bump __FreeBSD_version to 800100. 20090622: Layout of struct vnet has changed as routing related variables were moved to their own Vimage module. Modules need to be recompiled. Bump __FreeBSD_version to 800099. 20090619: NGROUPS_MAX and NGROUPS have been increased from 16 to 1023 and 1024 respectively. As long as no more than 16 groups per process are used, no changes should be visible. When more than 16 groups are used, old binaries may fail if they call getgroups() or getgrouplist() with statically sized storage. Recompiling will work around this, but applications should be modified to use dynamically allocated storage for group arrays as POSIX.1-2008 does not cap an implementation's number of supported groups at NGROUPS_MAX+1 as previous versions did. NFS and portalfs mounts may also be affected as the list of groups is truncated to 16. Users of NFS who use more than 16 groups, should take care that negative group permissions are not used on the exported file systems as they will not be reliable unless a GSSAPI based authentication method is used. 20090616: The compiling option ADAPTIVE_LOCKMGRS has been introduced. This option compiles in the support for adaptive spinning for lockmgrs which want to enable it. The lockinit() function now accepts the flag LK_ADAPTIVE in order to make the lock object subject to adaptive spinning when both held in write and read mode. 20090613: The layout of the structure returned by IEEE80211_IOC_STA_INFO has changed. User applications that use this ioctl need to be rebuilt. 20090611: The layout of struct thread has changed. Kernel and modules need to be rebuilt. 20090608: The layout of structs ifnet, domain, protosw and vnet_net has changed. Kernel modules need to be rebuilt. Bump __FreeBSD_version to 800097. 20090602: window(1) has been removed from the base system. It can now be installed from ports. The port is called misc/window. 20090601: The way we are storing and accessing `routing table' entries has changed. Programs reading the FIB, like netstat, need to be re-compiled. 20090601: A new netisr implementation has been added for FreeBSD 8. Network file system modules, such as igmp, ipdivert, and others, should be rebuilt. Bump __FreeBSD_version to 800096. 20090530: Remove the tunable/sysctl debug.mpsafevfs as its initial purpose is no more valid. 20090530: Add VOP_ACCESSX(9). File system modules need to be rebuilt. Bump __FreeBSD_version to 800094. 20090529: Add mnt_xflag field to 'struct mount'. File system modules need to be rebuilt. Bump __FreeBSD_version to 800093. 20090528: The compiling option ADAPTIVE_SX has been retired while it has been introduced the option NO_ADAPTIVE_SX which handles the reversed logic. The KPI for sx_init_flags() changes as accepting flags: SX_ADAPTIVESPIN flag has been retired while the SX_NOADAPTIVE flag has been introduced in order to handle the reversed logic. Bump __FreeBSD_version to 800092. 20090527: Add support for hierarchical jails. Remove global securelevel. Bump __FreeBSD_version to 800091. 20090523: The layout of struct vnet_net has changed, therefore modules need to be rebuilt. Bump __FreeBSD_version to 800090. 20090523: The newly imported zic(8) produces a new format in the output. Please run tzsetup(8) to install the newly created data to /etc/localtime. 20090520: The sysctl tree for the usb stack has renamed from hw.usb2.* to hw.usb.* and is now consistent again with previous releases. 20090520: 802.11 monitor mode support was revised and driver api's were changed. Drivers dependent on net80211 now support DLT_IEEE802_11_RADIO instead of DLT_IEEE802_11. No user-visible data structures were changed but applications that use DLT_IEEE802_11 may require changes. Bump __FreeBSD_version to 800088. 20090430: The layout of the following structs has changed: sysctl_oid, socket, ifnet, inpcbinfo, tcpcb, syncache_head, vnet_inet, vnet_inet6 and vnet_ipfw. Most modules need to be rebuild or panics may be experienced. World rebuild is required for correctly checking networking state from userland. Bump __FreeBSD_version to 800085. 20090429: MLDv2 and Source-Specific Multicast (SSM) have been merged to the IPv6 stack. VIMAGE hooks are in but not yet used. The implementation of SSM within FreeBSD's IPv6 stack closely follows the IPv4 implementation. For kernel developers: * The most important changes are that the ip6_output() and ip6_input() paths no longer take the IN6_MULTI_LOCK, and this lock has been downgraded to a non-recursive mutex. * As with the changes to the IPv4 stack to support SSM, filtering of inbound multicast traffic must now be performed by transport protocols within the IPv6 stack. This does not apply to TCP and SCTP, however, it does apply to UDP in IPv6 and raw IPv6. * The KPIs used by IPv6 multicast are similar to those used by the IPv4 stack, with the following differences: * im6o_mc_filter() is analogous to imo_multicast_filter(). * The legacy KAME entry points in6_joingroup and in6_leavegroup() are shimmed to in6_mc_join() and in6_mc_leave() respectively. * IN6_LOOKUP_MULTI() has been deprecated and removed. * IPv6 relies on MLD for the DAD mechanism. KAME's internal KPIs for MLDv1 have an additional 'timer' argument which is used to jitter the initial membership report for the solicited-node multicast membership on-link. * This is not strictly needed for MLDv2, which already jitters its report transmissions. However, the 'timer' argument is preserved in case MLDv1 is active on the interface. * The KAME linked-list based IPv6 membership implementation has been refactored to use a vector similar to that used by the IPv4 stack. Code which maintains a list of its own multicast memberships internally, e.g. carp, has been updated to reflect the new semantics. * There is a known Lock Order Reversal (LOR) due to in6_setscope() acquiring the IF_AFDATA_LOCK and being called within ip6_output(). Whilst MLDv2 tries to avoid this otherwise benign LOR, it is an implementation constraint which needs to be addressed in HEAD. For application developers: * The changes are broadly similar to those made for the IPv4 stack. * The use of IPv4 and IPv6 multicast socket options on the same socket, using mapped addresses, HAS NOT been tested or supported. * There are a number of issues with the implementation of various IPv6 multicast APIs which need to be resolved in the API surface before the implementation is fully compatible with KAME userland use, and these are mostly to do with interface index treatment. * The literature available discusses the use of either the delta / ASM API with setsockopt(2)/getsockopt(2), or the full-state / ASM API using setsourcefilter(3)/getsourcefilter(3). For more information please refer to RFC 3768, 'Socket Interface Extensions for Multicast Source Filters'. * Applications which use the published RFC 3678 APIs should be fine. For systems administrators: * The mtest(8) utility has been refactored to support IPv6, in addition to IPv4. Interface addresses are no longer accepted as arguments, their names must be used instead. The utility will map the interface name to its first IPv4 address as returned by getifaddrs(3). * The ifmcstat(8) utility has also been updated to print the MLDv2 endpoint state and source filter lists via sysctl(3). * The net.inet6.ip6.mcast.loop sysctl may be tuned to 0 to disable loopback of IPv6 multicast datagrams by default; it defaults to 1 to preserve the existing behaviour. Disabling multicast loopback is recommended for optimal system performance. * The IPv6 MROUTING code has been changed to examine this sysctl instead of attempting to perform a group lookup before looping back forwarded datagrams. Bump __FreeBSD_version to 800084. 20090422: Implement low-level Bluetooth HCI API. Bump __FreeBSD_version to 800083. 20090419: The layout of struct malloc_type, used by modules to register new memory allocation types, has changed. Most modules will need to be rebuilt or panics may be experienced. Bump __FreeBSD_version to 800081. 20090415: Anticipate overflowing inp_flags - add inp_flags2. This changes most offsets in inpcb, so checking v4 connection state will require a world rebuild. Bump __FreeBSD_version to 800080. 20090415: Add an llentry to struct route and struct route_in6. Modules embedding a struct route will need to be recompiled. Bump __FreeBSD_version to 800079. 20090414: The size of rt_metrics_lite and by extension rtentry has changed. Networking administration apps will need to be recompiled. The route command now supports show as an alias for get, weighting of routes, sticky and nostick flags to alter the behavior of stateful load balancing. Bump __FreeBSD_version to 800078. 20090408: Do not use Giant for kbdmux(4) locking. This is wrong and apparently causing more problems than it solves. This will re-open the issue where interrupt handlers may race with kbdmux(4) in polling mode. Typical symptoms include (but not limited to) duplicated and/or missing characters when low level console functions (such as gets) are used while interrupts are enabled (for example geli password prompt, mountroot prompt etc.). Disabling kbdmux(4) may help. 20090407: The size of structs vnet_net, vnet_inet and vnet_ipfw has changed; kernel modules referencing any of the above need to be recompiled. Bump __FreeBSD_version to 800075. 20090320: GEOM_PART has become the default partition slicer for storage devices, replacing GEOM_MBR, GEOM_BSD, GEOM_PC98 and GEOM_GPT slicers. It introduces some changes: MSDOS/EBR: the devices created from MSDOS extended partition entries (EBR) can be named differently than with GEOM_MBR and are now symlinks to devices with offset-based names. fstabs may need to be modified. BSD: the "geometry does not match label" warning is harmless in most cases but it points to problems in file system misalignment with disk geometry. The "c" partition is now implicit, covers the whole top-level drive and cannot be (mis)used by users. General: Kernel dumps are now not allowed to be written to devices whose partition types indicate they are meant to be used for file systems (or, in case of MSDOS partitions, as something else than the "386BSD" type). Most of these changes date approximately from 200812. 20090319: The uscanner(4) driver has been removed from the kernel. This follows Linux removing theirs in 2.6 and making libusb the default interface (supported by sane). 20090319: The multicast forwarding code has been cleaned up. netstat(1) only relies on KVM now for printing bandwidth upcall meters. The IPv4 and IPv6 modules are split into ip_mroute_mod and ip6_mroute_mod respectively. The config(5) options for statically compiling this code remain the same, i.e. 'options MROUTING'. 20090315: Support for the IFF_NEEDSGIANT network interface flag has been removed, which means that non-MPSAFE network device drivers are no longer supported. In particular, if_ar, if_sr, and network device drivers from the old (legacy) USB stack can no longer be built or used. 20090313: POSIX.1 Native Language Support (NLS) has been enabled in libc and a bunch of new language catalog files have also been added. This means that some common libc messages are now localized and they depend on the LC_MESSAGES environmental variable. 20090313: The k8temp(4) driver has been renamed to amdtemp(4) since support for Family 10 and Family 11 CPU families was added. 20090309: IGMPv3 and Source-Specific Multicast (SSM) have been merged to the IPv4 stack. VIMAGE hooks are in but not yet used. For kernel developers, the most important changes are that the ip_output() and ip_input() paths no longer take the IN_MULTI_LOCK(), and this lock has been downgraded to a non-recursive mutex. Transport protocols (UDP, Raw IP) are now responsible for filtering inbound multicast traffic according to group membership and source filters. The imo_multicast_filter() KPI exists for this purpose. Transports which do not use multicast (SCTP, TCP) already reject multicast by default. Forwarding and receive performance may improve as a mutex acquisition is no longer needed in the ip_input() low-level input path. in_addmulti() and in_delmulti() are shimmed to new KPIs which exist to support SSM in-kernel. For application developers, it is recommended that loopback of multicast datagrams be disabled for best performance, as this will still cause the lock to be taken for each looped-back datagram transmission. The net.inet.ip.mcast.loop sysctl may be tuned to 0 to disable loopback by default; it defaults to 1 to preserve the existing behaviour. For systems administrators, to obtain best performance with multicast reception and multiple groups, it is always recommended that a card with a suitably precise hash filter is used. Hash collisions will still result in the lock being taken within the transport protocol input path to check group membership. If deploying FreeBSD in an environment with IGMP snooping switches, it is recommended that the net.inet.igmp.sendlocal sysctl remain enabled; this forces 224.0.0.0/24 group membership to be announced via IGMP. The size of 'struct igmpstat' has changed; netstat needs to be recompiled to reflect this. Bump __FreeBSD_version to 800070. 20090309: libusb20.so.1 is now installed as libusb.so.1 and the ports system updated to use it. This requires a buildworld/installworld in order to update the library and dependencies (usbconfig, etc). Its advisable to rebuild all ports which uses libusb. More specific directions are given in the ports collection UPDATING file. Any /etc/libmap.conf entries for libusb are no longer required and can be removed. 20090302: A workaround is committed to allow the creation of System V shared memory segment of size > 2 GB on the 64-bit architectures. Due to a limitation of the existing ABI, the shm_segsz member of the struct shmid_ds, returned by shmctl(IPC_STAT) call is wrong for large segments. Note that limits must be explicitly raised to allow such segments to be created. 20090301: The layout of struct ifnet has changed, requiring a rebuild of all network device driver modules. 20090227: The /dev handling for the new USB stack has changed, a buildworld/installworld is required for libusb20. 20090223: The new USB2 stack has now been permanently moved in and all kernel and module names reverted to their previous values (eg, usb, ehci, ohci, ums, ...). The old usb stack can be compiled in by prefixing the name with the letter 'o', the old usb modules have been removed. Updating entry 20090216 for xorg and 20090215 for libmap may still apply. 20090217: The rc.conf(5) option if_up_delay has been renamed to defaultroute_delay to better reflect its purpose. If you have customized this setting in /etc/rc.conf you need to update it to use the new name. 20090216: xorg 7.4 wants to configure its input devices via hald which does not yet work with USB2. If the keyboard/mouse does not work in xorg then add Option "AllowEmptyInput" "off" to your ServerLayout section. This will cause X to use the configured kbd and mouse sections from your xorg.conf. 20090215: The GENERIC kernels for all architectures now default to the new USB2 stack. No kernel config options or code have been removed so if a problem arises please report it and optionally revert to the old USB stack. If you are loading USB kernel modules or have a custom kernel that includes GENERIC then ensure that usb names are also changed over, eg uftdi -> usb2_serial_ftdi. Older programs linked against the ports libusb 0.1 need to be redirected to the new stack's libusb20. /etc/libmap.conf can be used for this: # Map old usb library to new one for usb2 stack libusb-0.1.so.8 libusb20.so.1 20090209: All USB ethernet devices now attach as interfaces under the name ueN (eg. ue0). This is to provide a predictable name as vendors often change usb chipsets in a product without notice. 20090203: The ichsmb(4) driver has been changed to require SMBus slave addresses be left-justified (xxxxxxx0b) rather than right-justified. All of the other SMBus controller drivers require left-justified slave addresses, so this change makes all the drivers provide the same interface. 20090201: INET6 statistics (struct ip6stat) was updated. netstat(1) needs to be recompiled. 20090119: NTFS has been removed from GENERIC kernel on amd64 to match GENERIC on i386. Should not cause any issues since mount_ntfs(8) will load ntfs.ko module automatically when NTFS support is actually needed, unless ntfs.ko is not installed or security level prohibits loading kernel modules. If either is the case, "options NTFS" has to be added into kernel config. 20090115: TCP Appropriate Byte Counting (RFC 3465) support added to kernel. New field in struct tcpcb breaks ABI, so bump __FreeBSD_version to 800061. User space tools that rely on the size of struct tcpcb in tcp_var.h (e.g. sockstat) need to be recompiled. 20081225: ng_tty(4) module updated to match the new TTY subsystem. Due to API change, user-level applications must be updated. New API support added to mpd5 CVS and expected to be present in next mpd5.3 release. 20081219: With __FreeBSD_version 800060 the makefs tool is part of the base system (it was a port). 20081216: The afdata and ifnet locks have been changed from mutexes to rwlocks, network modules will need to be re-compiled. 20081214: __FreeBSD_version 800059 incorporates the new arp-v2 rewrite. RTF_CLONING, RTF_LLINFO and RTF_WASCLONED flags are eliminated. The new code reduced struct rtentry{} by 16 bytes on 32-bit architecture and 40 bytes on 64-bit architecture. The userland applications "arp" and "ndp" have been updated accordingly. The output from "netstat -r" shows only routing entries and none of the L2 information. 20081130: __FreeBSD_version 800057 marks the switchover from the binary ath hal to source code. Users must add the line: options AH_SUPPORT_AR5416 to their kernel config files when specifying: device ath_hal The ath_hal module no longer exists; the code is now compiled together with the driver in the ath module. It is now possible to tailor chip support (i.e. reduce the set of chips and thereby the code size); consult ath_hal(4) for details. 20081121: __FreeBSD_version 800054 adds memory barriers to , new interfaces to ifnet to facilitate multiple hardware transmit queues for cards that support them, and a lock-less ring-buffer implementation to enable drivers to more efficiently manage queueing of packets. 20081117: A new version of ZFS (version 13) has been merged to -HEAD. This version has zpool attribute "listsnapshots" off by default, which means "zfs list" does not show snapshots, and is the same as Solaris behavior. 20081028: dummynet(4) ABI has changed. ipfw(8) needs to be recompiled. 20081009: The uhci, ohci, ehci and slhci USB Host controller drivers have been put into separate modules. If you load the usb module separately through loader.conf you will need to load the appropriate *hci module as well. E.g. for a UHCI-based USB 2.0 controller add the following to loader.conf: uhci_load="YES" ehci_load="YES" 20081009: The ABI used by the PMC toolset has changed. Please keep userland (libpmc(3)) and the kernel module (hwpmc(4)) in sync. 20081009: atapci kernel module now includes only generic PCI ATA driver. AHCI driver moved to ataahci kernel module. All vendor-specific code moved into separate kernel modules: ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia 20080820: The TTY subsystem of the kernel has been replaced by a new implementation, which provides better scalability and an improved driver model. Most common drivers have been migrated to the new TTY subsystem, while others have not. The following drivers have not yet been ported to the new TTY layer: PCI/ISA: cy, digi, rc, rp, sio USB: ubser, ucycom Line disciplines: ng_h4, ng_tty, ppp, sl, snp Adding these drivers to your kernel configuration file shall cause compilation to fail. 20080818: ntpd has been upgraded to 4.2.4p5. 20080801: OpenSSH has been upgraded to 5.1p1. For many years, FreeBSD's version of OpenSSH preferred DSA over RSA for host and user authentication keys. With this upgrade, we've switched to the vendor's default of RSA over DSA. This may cause upgraded clients to warn about unknown host keys even for previously known hosts. Users should follow the usual procedure for verifying host keys before accepting the RSA key. This can be circumvented by setting the "HostKeyAlgorithms" option to "ssh-dss,ssh-rsa" in ~/.ssh/config or on the ssh command line. Please note that the sequence of keys offered for authentication has been changed as well. You may want to specify IdentityFile in a different order to revert this behavior. 20080713: The sio(4) driver has been removed from the i386 and amd64 kernel configuration files. This means uart(4) is now the default serial port driver on those platforms as well. To prevent collisions with the sio(4) driver, the uart(4) driver uses different names for its device nodes. This means the onboard serial port will now most likely be called "ttyu0" instead of "ttyd0". You may need to reconfigure applications to use the new device names. When using the serial port as a boot console, be sure to update /boot/device.hints and /etc/ttys before booting the new kernel. If you forget to do so, you can still manually specify the hints at the loader prompt: set hint.uart.0.at="isa" set hint.uart.0.port="0x3F8" set hint.uart.0.flags="0x10" set hint.uart.0.irq="4" boot -s 20080609: The gpt(8) utility has been removed. Use gpart(8) to partition disks instead. 20080603: The version that Linuxulator emulates was changed from 2.4.2 to 2.6.16. If you experience any problems with Linux binaries please try to set sysctl compat.linux.osrelease to 2.4.2 and if it fixes the problem contact emulation mailing list. 20080525: ISDN4BSD (I4B) was removed from the src tree. You may need to update a your kernel configuration and remove relevant entries. 20080509: I have checked in code to support multiple routing tables. See the man pages setfib(1) and setfib(2). This is a hopefully backwards compatible version, but to make use of it you need to compile your kernel with options ROUTETABLES=2 (or more up to 16). 20080420: The 802.11 wireless support was redone to enable multi-bss operation on devices that are capable. The underlying device is no longer used directly but instead wlanX devices are cloned with ifconfig. This requires changes to rc.conf files. For example, change: ifconfig_ath0="WPA DHCP" to wlans_ath0=wlan0 ifconfig_wlan0="WPA DHCP" see rc.conf(5) for more details. In addition, mergemaster of /etc/rc.d is highly recommended. Simultaneous update of userland and kernel wouldn't hurt either. As part of the multi-bss changes the wlan_scan_ap and wlan_scan_sta modules were merged into the base wlan module. All references to these modules (e.g. in kernel config files) must be removed. 20080408: psm(4) has gained write(2) support in native operation level. Arbitrary commands can be written to /dev/psm%d and status can be read back from it. Therefore, an application is responsible for status validation and error recovery. It is a no-op in other operation levels. 20080312: Support for KSE threading has been removed from the kernel. To run legacy applications linked against KSE libmap.conf may be used. The following libmap.conf may be used to ensure compatibility with any prior release: libpthread.so.1 libthr.so.1 libpthread.so.2 libthr.so.2 libkse.so.3 libthr.so.3 20080301: The layout of struct vmspace has changed. This affects libkvm and any executables that link against libkvm and use the kvm_getprocs() function. In particular, but not exclusively, it affects ps(1), fstat(1), pkill(1), systat(1), top(1) and w(1). The effects are minimal, but it's advisable to upgrade world nonetheless. 20080229: The latest em driver no longer has support in it for the 82575 adapter, this is now moved to the igb driver. The split was done to make new features that are incompatible with older hardware easier to do. 20080220: The new geom_lvm(4) geom class has been renamed to geom_linux_lvm(4), likewise the kernel option is now GEOM_LINUX_LVM. 20080211: The default NFS mount mode has changed from UDP to TCP for increased reliability. If you rely on (insecurely) NFS mounting across a firewall you may need to update your firewall rules. 20080208: Belatedly note the addition of m_collapse for compacting mbuf chains. 20080126: The fts(3) structures have been changed to use adequate integer types for their members and so to be able to cope with huge file trees. The old fts(3) ABI is preserved through symbol versioning in libc, so third-party binaries using fts(3) should still work, although they will not take advantage of the extended types. At the same time, some third-party software might fail to build after this change due to unportable assumptions made in its source code about fts(3) structure members. Such software should be fixed by its vendor or, in the worst case, in the ports tree. FreeBSD_version 800015 marks this change for the unlikely case that a portable fix is impossible. 20080123: To upgrade to -current after this date, you must be running FreeBSD not older than 6.0-RELEASE. Upgrading to -current from 5.x now requires a stop over at RELENG_6 or RELENG_7 systems. 20071128: The ADAPTIVE_GIANT kernel option has been retired because its functionality is the default now. 20071118: The AT keyboard emulation of sunkbd(4) has been turned on by default. In order to make the special symbols of the Sun keyboards driven by sunkbd(4) work under X these now have to be configured the same way as Sun USB keyboards driven by ukbd(4) (which also does AT keyboard emulation), f.e.: Option "XkbLayout" "us" Option "XkbRules" "xorg" Option "XkbSymbols" "pc(pc105)+sun_vndr/usb(sun_usb)+us" 20071024: It has been decided that it is desirable to provide ABI backwards compatibility to the FreeBSD 4/5/6 versions of the PCIOCGETCONF, PCIOCREAD and PCIOCWRITE IOCTLs, which was broken with the introduction of PCI domain support (see the 20070930 entry). Unfortunately, this required the ABI of PCIOCGETCONF to be broken again in order to be able to provide backwards compatibility to the old version of that IOCTL. Thus consumers of PCIOCGETCONF have to be recompiled again. As for prominent ports this affects neither pciutils nor xorg-server this time, the hal port needs to be rebuilt however. 20071020: The misnamed kthread_create() and friends have been renamed to kproc_create() etc. Many of the callers already used kproc_start().. I will return kthread_create() and friends in a while with implementations that actually create threads, not procs. Renaming corresponds with version 800002. 20071010: RELENG_7 branched. COMMON ITEMS: General Notes ------------- Avoid using make -j when upgrading. While generally safe, there are sometimes problems using -j to upgrade. If your upgrade fails with -j, please try again without -j. From time to time in the past there have been problems using -j with buildworld and/or installworld. This is especially true when upgrading between "distant" versions (eg one that cross a major release boundary or several minor releases, or when several months have passed on the -current branch). Sometimes, obscure build problems are the result of environment poisoning. This can happen because the make utility reads its environment when searching for values for global variables. To run your build attempts in an "environmental clean room", prefix all make commands with 'env -i '. See the env(1) manual page for more details. When upgrading from one major version to another it is generally best to upgrade to the latest code in the currently installed branch first, then do an upgrade to the new branch. This is the best-tested upgrade path, and has the highest probability of being successful. Please try this approach before reporting problems with a major version upgrade. When upgrading a live system, having a root shell around before installing anything can help undo problems. Not having a root shell around can lead to problems if pam has changed too much from your starting point to allow continued authentication after the upgrade. ZFS notes --------- When upgrading the boot ZFS pool to a new version, always follow these two steps: 1.) recompile and reinstall the ZFS boot loader and boot block (this is part of "make buildworld" and "make installworld") 2.) update the ZFS boot block on your boot drive The following example updates the ZFS boot block on the first partition (freebsd-boot) of a GPT partitioned drive ad0: "gpart bootcode -p /boot/gptzfsboot -i 1 ad0" Non-boot pools do not need these updates. To build a kernel ----------------- If you are updating from a prior version of FreeBSD (even one just a few days old), you should follow this procedure. It is the most failsafe as it uses a /usr/obj tree with a fresh mini-buildworld, make kernel-toolchain make -DALWAYS_CHECK_MAKE buildkernel KERNCONF=YOUR_KERNEL_HERE make -DALWAYS_CHECK_MAKE installkernel KERNCONF=YOUR_KERNEL_HERE To test a kernel once --------------------- If you just want to boot a kernel once (because you are not sure if it works, or if you want to boot a known bad kernel to provide debugging information) run make installkernel KERNCONF=YOUR_KERNEL_HERE KODIR=/boot/testkernel nextboot -k testkernel To just build a kernel when you know that it won't mess you up -------------------------------------------------------------- This assumes you are already running a CURRENT system. Replace ${arch} with the architecture of your machine (e.g. "i386", "arm", "amd64", "ia64", "pc98", "sparc64", "powerpc", "mips", etc). cd src/sys/${arch}/conf config KERNEL_NAME_HERE cd ../compile/KERNEL_NAME_HERE make depend make make install If this fails, go to the "To build a kernel" section. To rebuild everything and install it on the current system. ----------------------------------------------------------- # Note: sometimes if you are running current you gotta do more than # is listed here if you are upgrading from a really old current. make buildworld make kernel KERNCONF=YOUR_KERNEL_HERE [1] [3] mergemaster -p [5] make installworld mergemaster -i [4] make delete-old [6] To cross-install current onto a separate partition -------------------------------------------------- # In this approach we use a separate partition to hold # current's root, 'usr', and 'var' directories. A partition # holding "/", "/usr" and "/var" should be about 2GB in # size. make buildworld make buildkernel KERNCONF=YOUR_KERNEL_HERE make installworld DESTDIR=${CURRENT_ROOT} make distribution DESTDIR=${CURRENT_ROOT} # if newfs'd make installkernel KERNCONF=YOUR_KERNEL_HERE DESTDIR=${CURRENT_ROOT} cp /etc/fstab ${CURRENT_ROOT}/etc/fstab # if newfs'd To upgrade in-place from stable to current ---------------------------------------------- make buildworld [9] make kernel KERNCONF=YOUR_KERNEL_HERE [8] [1] [3] mergemaster -p [5] make installworld mergemaster -i [4] make delete-old [6] Make sure that you've read the UPDATING file to understand the tweaks to various things you need. At this point in the life cycle of current, things change often and you are on your own to cope. The defaults can also change, so please read ALL of the UPDATING entries. Also, if you are tracking -current, you must be subscribed to freebsd-current@freebsd.org. Make sure that before you update your sources that you have read and understood all the recent messages there. If in doubt, please track -stable which has much fewer pitfalls. [1] If you have third party modules, such as vmware, you should disable them at this point so they don't crash your system on reboot. [3] From the bootblocks, boot -s, and then do fsck -p mount -u / mount -a cd src adjkerntz -i # if CMOS is wall time Also, when doing a major release upgrade, it is required that you boot into single user mode to do the installworld. [4] Note: This step is non-optional. Failure to do this step can result in a significant reduction in the functionality of the system. Attempting to do it by hand is not recommended and those that pursue this avenue should read this file carefully, as well as the archives of freebsd-current and freebsd-hackers mailing lists for potential gotchas. The -U option is also useful to consider. See mergemaster(8) for more information. [5] Usually this step is a noop. However, from time to time you may need to do this if you get unknown user in the following step. It never hurts to do it all the time. You may need to install a new mergemaster (cd src/usr.sbin/mergemaster && make install) after the buildworld before this step if you last updated from current before 20130425 or from -stable before 20130430. [6] This only deletes old files and directories. Old libraries can be deleted by "make delete-old-libs", but you have to make sure that no program is using those libraries anymore. [8] In order to have a kernel that can run the 4.x binaries needed to do an installworld, you must include the COMPAT_FREEBSD4 option in your kernel. Failure to do so may leave you with a system that is hard to boot to recover. A similar kernel option COMPAT_FREEBSD5 is required to run the 5.x binaries on more recent kernels. And so on for COMPAT_FREEBSD6 and COMPAT_FREEBSD7. Make sure that you merge any new devices from GENERIC since the last time you updated your kernel config file. [9] When checking out sources, you must include the -P flag to have cvs prune empty directories. If CPUTYPE is defined in your /etc/make.conf, make sure to use the "?=" instead of the "=" assignment operator, so that buildworld can override the CPUTYPE if it needs to. MAKEOBJDIRPREFIX must be defined in an environment variable, and not on the command line, or in /etc/make.conf. buildworld will warn if it is improperly defined. FORMAT: This file contains a list, in reverse chronological order, of major breakages in tracking -current. It is not guaranteed to be a complete list of such breakages, and only contains entries since October 10, 2007. If you need to see UPDATING entries from before that date, you will need to fetch an UPDATING file from an older FreeBSD release. Copyright information: Copyright 1998-2009 M. Warner Losh. All Rights Reserved. Redistribution, publication, translation and use, with or without modification, in full or in part, in any form or format of this document are permitted without further permission from the author. THIS DOCUMENT IS PROVIDED BY WARNER LOSH ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WARNER LOSH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Contact Warner Losh if you have any questions about your use of this document. $FreeBSD$ Index: releng/10.1/crypto/openssl/apps/dhparam.c =================================================================== --- releng/10.1/crypto/openssl/apps/dhparam.c (revision 284294) +++ releng/10.1/crypto/openssl/apps/dhparam.c (revision 284295) @@ -1,559 +1,559 @@ /* apps/dhparam.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* ==================================================================== * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ #include /* for OPENSSL_NO_DH */ #ifndef OPENSSL_NO_DH #include #include #include #include #include "apps.h" #include #include #include #include #include #include #ifndef OPENSSL_NO_DSA #include #endif #undef PROG #define PROG dhparam_main -#define DEFBITS 512 +#define DEFBITS 2048 /* -inform arg - input format - default PEM (DER or PEM) * -outform arg - output format - default PEM * -in arg - input file - default stdin * -out arg - output file - default stdout * -dsaparam - read or generate DSA parameters, convert to DH * -check - check the parameters are ok * -noout * -text * -C */ static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb); int MAIN(int, char **); int MAIN(int argc, char **argv) { DH *dh=NULL; int i,badops=0,text=0; #ifndef OPENSSL_NO_DSA int dsaparam=0; #endif BIO *in=NULL,*out=NULL; int informat,outformat,check=0,noout=0,C=0,ret=1; char *infile,*outfile,*prog; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif int num = 0, g = 0; apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; infile=NULL; outfile=NULL; informat=FORMAT_PEM; outformat=FORMAT_PEM; prog=argv[0]; argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-check") == 0) check=1; else if (strcmp(*argv,"-text") == 0) text=1; #ifndef OPENSSL_NO_DSA else if (strcmp(*argv,"-dsaparam") == 0) dsaparam=1; #endif else if (strcmp(*argv,"-C") == 0) C=1; else if (strcmp(*argv,"-noout") == 0) noout=1; else if (strcmp(*argv,"-2") == 0) g=2; else if (strcmp(*argv,"-5") == 0) g=5; else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else if (((sscanf(*argv,"%d",&num) == 0) || (num <= 0))) goto bad; argv++; argc--; } if (badops) { bad: BIO_printf(bio_err,"%s [options] [numbits]\n",prog); BIO_printf(bio_err,"where options are\n"); BIO_printf(bio_err," -inform arg input format - one of DER PEM\n"); BIO_printf(bio_err," -outform arg output format - one of DER PEM\n"); BIO_printf(bio_err," -in arg input file\n"); BIO_printf(bio_err," -out arg output file\n"); #ifndef OPENSSL_NO_DSA BIO_printf(bio_err," -dsaparam read or generate DSA parameters, convert to DH\n"); #endif BIO_printf(bio_err," -check check the DH parameters\n"); BIO_printf(bio_err," -text print a text form of the DH parameters\n"); BIO_printf(bio_err," -C Output C code\n"); BIO_printf(bio_err," -2 generate parameters using 2 as the generator value\n"); BIO_printf(bio_err," -5 generate parameters using 5 as the generator value\n"); - BIO_printf(bio_err," numbits number of bits in to generate (default 512)\n"); + BIO_printf(bio_err," numbits number of bits in to generate (default 2048)\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err," - load the file (or the files in the directory) into\n"); BIO_printf(bio_err," the random number generator\n"); BIO_printf(bio_err," -noout no output\n"); goto end; } ERR_load_crypto_strings(); #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if (g && !num) num = DEFBITS; #ifndef OPENSSL_NO_DSA if (dsaparam) { if (g) { BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); goto end; } } else #endif { /* DH parameters */ if (num && !g) g = 2; } if(num) { BN_GENCB cb; BN_GENCB_set(&cb, dh_cb, bio_err); if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); #ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa = DSA_new(); BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num); if(!dsa || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, &cb)) { if(dsa) DSA_free(dsa); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else #endif { dh = DH_new(); BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g); BIO_printf(bio_err,"This is going to take a long time\n"); if(!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) { ERR_print_errors(bio_err); goto end; } } app_RAND_write_file(NULL, bio_err); } else { in=BIO_new(BIO_s_file()); if (in == NULL) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); goto end; } } if (informat != FORMAT_ASN1 && informat != FORMAT_PEM) { BIO_printf(bio_err,"bad input format specified\n"); goto end; } #ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; if (informat == FORMAT_ASN1) dsa=d2i_DSAparams_bio(in,NULL); else /* informat == FORMAT_PEM */ dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL); if (dsa == NULL) { BIO_printf(bio_err,"unable to load DSA parameters\n"); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else #endif { if (informat == FORMAT_ASN1) dh=d2i_DHparams_bio(in,NULL); else /* informat == FORMAT_PEM */ dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL); if (dh == NULL) { BIO_printf(bio_err,"unable to load DH parameters\n"); ERR_print_errors(bio_err); goto end; } } /* dh != NULL */ } out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (text) { DHparams_print(out,dh); } if (check) { if (!DH_check(dh,&i)) { ERR_print_errors(bio_err); goto end; } if (i & DH_CHECK_P_NOT_PRIME) printf("p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) printf("p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) printf("unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) printf("the g value is not a generator\n"); if (i == 0) printf("DH parameters appear to be ok.\n"); } if (C) { unsigned char *data; int len,l,bits; len=BN_num_bytes(dh->p); bits=BN_num_bits(dh->p); data=(unsigned char *)OPENSSL_malloc(len); if (data == NULL) { perror("OPENSSL_malloc"); goto end; } printf("#ifndef HEADER_DH_H\n" "#include \n" "#endif\n"); printf("DH *get_dh%d()\n\t{\n",bits); l=BN_bn2bin(dh->p,data); printf("\tstatic unsigned char dh%d_p[]={",bits); for (i=0; ig,data); printf("\tstatic unsigned char dh%d_g[]={",bits); for (i=0; ip=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", bits,bits); printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", bits,bits); printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); printf("\t\t{ DH_free(dh); return(NULL); }\n"); if (dh->length) printf("\tdh->length = %ld;\n", dh->length); printf("\treturn(dh);\n\t}\n"); OPENSSL_free(data); } if (!noout) { if (outformat == FORMAT_ASN1) i=i2d_DHparams_bio(out,dh); else if (outformat == FORMAT_PEM) i=PEM_write_bio_DHparams(out,dh); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write DH parameters\n"); ERR_print_errors(bio_err); goto end; } } ret=0; end: if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (dh != NULL) DH_free(dh); apps_shutdown(); OPENSSL_EXIT(ret); } /* dh_cb is identical to dsa_cb in apps/dsaparam.c */ static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb) { char c='*'; if (p == 0) c='.'; if (p == 1) c='+'; if (p == 2) c='*'; if (p == 3) c='\n'; BIO_write(cb->arg,&c,1); (void)BIO_flush(cb->arg); #ifdef LINT p=n; #endif return 1; } #else /* !OPENSSL_NO_DH */ # if PEDANTIC static void *dummy=&dummy; # endif #endif Index: releng/10.1/crypto/openssl/apps/gendh.c =================================================================== --- releng/10.1/crypto/openssl/apps/gendh.c (revision 284294) +++ releng/10.1/crypto/openssl/apps/gendh.c (revision 284295) @@ -1,241 +1,241 @@ /* apps/gendh.c */ /* obsoleted by dhparam.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include /* Until the key-gen callbacks are modified to use newer prototypes, we allow * deprecated functions for openssl-internal code */ #ifdef OPENSSL_NO_DEPRECATED #undef OPENSSL_NO_DEPRECATED #endif #ifndef OPENSSL_NO_DH #include #include #include #include #include "apps.h" #include #include #include #include #include #include #include -#define DEFBITS 512 +#define DEFBITS 2048 #undef PROG #define PROG gendh_main static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb); int MAIN(int, char **); int MAIN(int argc, char **argv) { BN_GENCB cb; DH *dh=NULL; int ret=1,num=DEFBITS; int g=2; char *outfile=NULL; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif BIO *out=NULL; apps_startup(); BN_GENCB_set(&cb, dh_cb, bio_err); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; argv++; argc--; for (;;) { if (argc <= 0) break; if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-2") == 0) g=2; /* else if (strcmp(*argv,"-3") == 0) g=3; */ else if (strcmp(*argv,"-5") == 0) g=5; #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else break; argv++; argc--; } if ((argc >= 1) && ((sscanf(*argv,"%d",&num) == 0) || (num < 0))) { bad: BIO_printf(bio_err,"usage: gendh [args] [numbits]\n"); BIO_printf(bio_err," -out file - output the key to 'file\n"); BIO_printf(bio_err," -2 - use 2 as the generator value\n"); /* BIO_printf(bio_err," -3 - use 3 as the generator value\n"); */ BIO_printf(bio_err," -5 - use 5 as the generator value\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e - use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err," - load the file (or the files in the directory) into\n"); BIO_printf(bio_err," the random number generator\n"); goto end; } #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g); BIO_printf(bio_err,"This is going to take a long time\n"); if(((dh = DH_new()) == NULL) || !DH_generate_parameters_ex(dh, num, g, &cb)) goto end; app_RAND_write_file(NULL, bio_err); if (!PEM_write_bio_DHparams(out,dh)) goto end; ret=0; end: if (ret != 0) ERR_print_errors(bio_err); if (out != NULL) BIO_free_all(out); if (dh != NULL) DH_free(dh); apps_shutdown(); OPENSSL_EXIT(ret); } static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb) { char c='*'; if (p == 0) c='.'; if (p == 1) c='+'; if (p == 2) c='*'; if (p == 3) c='\n'; BIO_write(cb->arg,&c,1); (void)BIO_flush(cb->arg); #ifdef LINT p=n; #endif return 1; } #else /* !OPENSSL_NO_DH */ # if PEDANTIC static void *dummy=&dummy; # endif #endif Index: releng/10.1/crypto/openssl/apps/s_server.c =================================================================== --- releng/10.1/crypto/openssl/apps/s_server.c (revision 284294) +++ releng/10.1/crypto/openssl/apps/s_server.c (revision 284295) @@ -1,3041 +1,3058 @@ /* apps/s_server.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* ==================================================================== * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ /* ==================================================================== * Copyright 2005 Nokia. All rights reserved. * * The portions of the attached software ("Contribution") is developed by * Nokia Corporation and is licensed pursuant to the OpenSSL open source * license. * * The Contribution, originally written by Mika Kousa and Pasi Eronen of * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites * support (see RFC 4279) to OpenSSL. * * No patent licenses or other rights except those expressly stated in * the OpenSSL open source license shall be deemed granted or received * expressly, by implication, estoppel, or otherwise. * * No assurances are provided by Nokia that the Contribution does not * infringe the patent or other intellectual property rights of any third * party or that the license provides you with all the necessary rights * to make use of the Contribution. * * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR * OTHERWISE. */ /* Until the key-gen callbacks are modified to use newer prototypes, we allow * deprecated functions for openssl-internal code */ #ifdef OPENSSL_NO_DEPRECATED #undef OPENSSL_NO_DEPRECATED #endif #include #include #include #include #include #include #ifdef OPENSSL_NO_STDIO #define APPS_WIN16 #endif #if !defined(OPENSSL_SYS_NETWARE) /* conflicts with winsock2 stuff on netware */ #include #endif /* With IPv6, it looks like Digital has mixed up the proper order of recursive header file inclusion, resulting in the compiler complaining that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is needed to have fileno() declared correctly... So let's define u_int */ #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) #define __U_INT typedef unsigned int u_int; #endif #include #include #define USE_SOCKETS #include "apps.h" #include #include #include #include #include #include #ifndef OPENSSL_NO_DH #include #endif #ifndef OPENSSL_NO_RSA #include #endif #ifndef OPENSSL_NO_SRP #include #endif #include "s_apps.h" #include "timeouts.h" #if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ #undef FIONBIO #endif #if defined(OPENSSL_SYS_BEOS_R5) #include #endif #ifndef OPENSSL_NO_RSA static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); #endif static int sv_body(char *hostname, int s, unsigned char *context); static int www_body(char *hostname, int s, unsigned char *context); static void close_accept_socket(void ); static void sv_usage(void); static int init_ssl_connection(SSL *s); static void print_stats(BIO *bp,SSL_CTX *ctx); static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len); #ifndef OPENSSL_NO_DH static DH *load_dh_param(const char *dhfile); -static DH *get_dh512(void); +static DH *get_dh2048(void); #endif #ifdef MONOLITH static void s_server_init(void); #endif #ifndef OPENSSL_NO_DH -static unsigned char dh512_p[]={ - 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, - 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, - 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, - 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, - 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, - 0x47,0x74,0xE8,0x33, - }; -static unsigned char dh512_g[]={ +static unsigned char dh2048_p[] = { + 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6, + 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1, + 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9, + 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD, + 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17, + 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F, + 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD, + 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30, + 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E, + 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4, + 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58, + 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B, + 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C, + 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B, + 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD, + 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C, + 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, + 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, + 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, + 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, + 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, + 0xE9,0x32,0x0B,0x3B, +}; + +static unsigned char dh2048_g[] = { 0x02, - }; +}; -static DH *get_dh512(void) - { - DH *dh=NULL; +DH *get_dh2048() +{ + DH *dh; - if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); - dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); - if ((dh->p == NULL) || (dh->g == NULL)) - return(NULL); - return(dh); + if ((dh = DH_new()) == NULL) + return NULL; + dh->p=BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); + dh->g=BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL); + if (dh->p == NULL || dh->g == NULL) { + DH_free(dh); + return NULL; } + return dh; +} #endif /* static int load_CA(SSL_CTX *ctx, char *file);*/ #undef BUFSIZZ #define BUFSIZZ 16*1024 static int bufsize=BUFSIZZ; static int accept_socket= -1; #define TEST_CERT "server.pem" #ifndef OPENSSL_NO_TLSEXT #define TEST_CERT2 "server2.pem" #endif #undef PROG #define PROG s_server_main extern int verify_depth, verify_return_error; static char *cipher=NULL; static int s_server_verify=SSL_VERIFY_NONE; static int s_server_session_id_context = 1; /* anything will do */ static const char *s_cert_file=TEST_CERT,*s_key_file=NULL; #ifndef OPENSSL_NO_TLSEXT static const char *s_cert_file2=TEST_CERT2,*s_key_file2=NULL; #endif static char *s_dcert_file=NULL,*s_dkey_file=NULL; #ifdef FIONBIO static int s_nbio=0; #endif static int s_nbio_test=0; int s_crlf=0; static SSL_CTX *ctx=NULL; #ifndef OPENSSL_NO_TLSEXT static SSL_CTX *ctx2=NULL; #endif static int www=0; static BIO *bio_s_out=NULL; static int s_debug=0; #ifndef OPENSSL_NO_TLSEXT static int s_tlsextdebug=0; static int s_tlsextstatus=0; static int cert_status_cb(SSL *s, void *arg); #endif static int s_msg=0; static int s_quiet=0; static char *keymatexportlabel=NULL; static int keymatexportlen=20; static int hack=0; #ifndef OPENSSL_NO_ENGINE static char *engine_id=NULL; #endif static const char *session_id_prefix=NULL; static int enable_timeouts = 0; static long socket_mtu; #ifndef OPENSSL_NO_DTLS1 static int cert_chain = 0; #endif #ifndef OPENSSL_NO_PSK static char *psk_identity="Client_identity"; char *psk_key=NULL; /* by default PSK is not used */ static unsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) { unsigned int psk_len = 0; int ret; BIGNUM *bn = NULL; if (s_debug) BIO_printf(bio_s_out,"psk_server_cb\n"); if (!identity) { BIO_printf(bio_err,"Error: client did not send PSK identity\n"); goto out_err; } if (s_debug) BIO_printf(bio_s_out,"identity_len=%d identity=%s\n", identity ? (int)strlen(identity) : 0, identity); /* here we could lookup the given identity e.g. from a database */ if (strcmp(identity, psk_identity) != 0) { BIO_printf(bio_s_out, "PSK error: client identity not found" " (got '%s' expected '%s')\n", identity, psk_identity); goto out_err; } if (s_debug) BIO_printf(bio_s_out, "PSK client identity found\n"); /* convert the PSK key to binary */ ret = BN_hex2bn(&bn, psk_key); if (!ret) { BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", psk_key); if (bn) BN_free(bn); return 0; } if (BN_num_bytes(bn) > (int)max_psk_len) { BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n", max_psk_len, BN_num_bytes(bn)); BN_free(bn); return 0; } ret = BN_bn2bin(bn, psk); BN_free(bn); if (ret < 0) goto out_err; psk_len = (unsigned int)ret; if (s_debug) BIO_printf(bio_s_out, "fetched PSK len=%d\n", psk_len); return psk_len; out_err: if (s_debug) BIO_printf(bio_err, "Error in PSK server callback\n"); return 0; } #endif #ifndef OPENSSL_NO_SRP /* This is a context that we pass to callbacks */ typedef struct srpsrvparm_st { char *login; SRP_VBASE *vb; SRP_user_pwd *user; } srpsrvparm; /* This callback pretends to require some asynchronous logic in order to obtain a verifier. When the callback is called for a new connection we return with a negative value. This will provoke the accept etc to return with an LOOKUP_X509. The main logic of the reinvokes the suspended call (which would normally occur after a worker has finished) and we set the user parameters. */ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) { srpsrvparm *p = (srpsrvparm *)arg; if (p->login == NULL && p->user == NULL ) { p->login = SSL_get_srp_username(s); BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); return (-1) ; } if (p->user == NULL) { BIO_printf(bio_err, "User %s doesn't exist\n", p->login); return SSL3_AL_FATAL; } if (SSL_set_srp_server_param(s, p->user->N, p->user->g, p->user->s, p->user->v, p->user->info) < 0) { *ad = SSL_AD_INTERNAL_ERROR; return SSL3_AL_FATAL; } BIO_printf(bio_err, "SRP parameters set: username = \"%s\" info=\"%s\" \n", p->login,p->user->info); /* need to check whether there are memory leaks */ p->user = NULL; p->login = NULL; return SSL_ERROR_NONE; } #endif #ifdef MONOLITH static void s_server_init(void) { accept_socket=-1; cipher=NULL; s_server_verify=SSL_VERIFY_NONE; s_dcert_file=NULL; s_dkey_file=NULL; s_cert_file=TEST_CERT; s_key_file=NULL; #ifndef OPENSSL_NO_TLSEXT s_cert_file2=TEST_CERT2; s_key_file2=NULL; ctx2=NULL; #endif #ifdef FIONBIO s_nbio=0; #endif s_nbio_test=0; ctx=NULL; www=0; bio_s_out=NULL; s_debug=0; s_msg=0; s_quiet=0; hack=0; #ifndef OPENSSL_NO_ENGINE engine_id=NULL; #endif } #endif static void sv_usage(void) { BIO_printf(bio_err,"usage: s_server [args ...]\n"); BIO_printf(bio_err,"\n"); BIO_printf(bio_err," -accept arg - port to accept on (default is %d)\n",PORT); BIO_printf(bio_err," -context arg - set session ID context\n"); BIO_printf(bio_err," -verify arg - turn on peer certificate verification\n"); BIO_printf(bio_err," -Verify arg - turn on peer certificate verification, must have a cert.\n"); BIO_printf(bio_err," -verify_return_error - return verification errors\n"); BIO_printf(bio_err," -cert arg - certificate file to use\n"); BIO_printf(bio_err," (default is %s)\n",TEST_CERT); BIO_printf(bio_err," -crl_check - check the peer certificate has not been revoked by its CA.\n" \ " The CRL(s) are appended to the certificate file\n"); BIO_printf(bio_err," -crl_check_all - check the peer certificate has not been revoked by its CA\n" \ " or any other CRL in the CA chain. CRL(s) are appened to the\n" \ " the certificate file.\n"); BIO_printf(bio_err," -certform arg - certificate format (PEM or DER) PEM default\n"); BIO_printf(bio_err," -key arg - Private Key file to use, in cert file if\n"); BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT); BIO_printf(bio_err," -keyform arg - key format (PEM, DER or ENGINE) PEM default\n"); BIO_printf(bio_err," -pass arg - private key file pass phrase source\n"); BIO_printf(bio_err," -dcert arg - second certificate file to use (usually for DSA)\n"); BIO_printf(bio_err," -dcertform x - second certificate format (PEM or DER) PEM default\n"); BIO_printf(bio_err," -dkey arg - second private key file to use (usually for DSA)\n"); BIO_printf(bio_err," -dkeyform arg - second key format (PEM, DER or ENGINE) PEM default\n"); BIO_printf(bio_err," -dpass arg - second private key file pass phrase source\n"); BIO_printf(bio_err," -dhparam arg - DH parameter file to use, in cert file if not specified\n"); BIO_printf(bio_err," or a default set of parameters is used\n"); #ifndef OPENSSL_NO_ECDH BIO_printf(bio_err," -named_curve arg - Elliptic curve name to use for ephemeral ECDH keys.\n" \ " Use \"openssl ecparam -list_curves\" for all names\n" \ " (default is nistp256).\n"); #endif #ifdef FIONBIO BIO_printf(bio_err," -nbio - Run with non-blocking IO\n"); #endif BIO_printf(bio_err," -nbio_test - test with the non-blocking test bio\n"); BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); BIO_printf(bio_err," -debug - Print more output\n"); BIO_printf(bio_err," -msg - Show protocol messages\n"); BIO_printf(bio_err," -state - Print the SSL states\n"); BIO_printf(bio_err," -CApath arg - PEM format directory of CA's\n"); BIO_printf(bio_err," -CAfile arg - PEM format file of CA's\n"); BIO_printf(bio_err," -nocert - Don't use any certificates (Anon-DH)\n"); BIO_printf(bio_err," -cipher arg - play with 'openssl ciphers' to see what goes here\n"); BIO_printf(bio_err," -serverpref - Use server's cipher preferences\n"); BIO_printf(bio_err," -quiet - No server output\n"); BIO_printf(bio_err," -no_tmp_rsa - Do not generate a tmp RSA key\n"); #ifndef OPENSSL_NO_PSK BIO_printf(bio_err," -psk_hint arg - PSK identity hint to use\n"); BIO_printf(bio_err," -psk arg - PSK in hex (without 0x)\n"); # ifndef OPENSSL_NO_JPAKE BIO_printf(bio_err," -jpake arg - JPAKE secret to use\n"); # endif #endif #ifndef OPENSSL_NO_SRP BIO_printf(bio_err," -srpvfile file - The verifier file for SRP\n"); BIO_printf(bio_err," -srpuserseed string - A seed string for a default user salt.\n"); #endif BIO_printf(bio_err," -ssl2 - Just talk SSLv2\n"); #ifndef OPENSSL_NO_SSL3_METHOD BIO_printf(bio_err," -ssl3 - Just talk SSLv3\n"); #endif BIO_printf(bio_err," -tls1_2 - Just talk TLSv1.2\n"); BIO_printf(bio_err," -tls1_1 - Just talk TLSv1.1\n"); BIO_printf(bio_err," -tls1 - Just talk TLSv1\n"); BIO_printf(bio_err," -dtls1 - Just talk DTLSv1\n"); BIO_printf(bio_err," -timeout - Enable timeouts\n"); BIO_printf(bio_err," -mtu - Set link layer MTU\n"); BIO_printf(bio_err," -chain - Read a certificate chain\n"); BIO_printf(bio_err," -no_ssl2 - Just disable SSLv2\n"); BIO_printf(bio_err," -no_ssl3 - Just disable SSLv3\n"); BIO_printf(bio_err," -no_tls1 - Just disable TLSv1\n"); BIO_printf(bio_err," -no_tls1_1 - Just disable TLSv1.1\n"); BIO_printf(bio_err," -no_tls1_2 - Just disable TLSv1.2\n"); #ifndef OPENSSL_NO_DH BIO_printf(bio_err," -no_dhe - Disable ephemeral DH\n"); #endif #ifndef OPENSSL_NO_ECDH BIO_printf(bio_err," -no_ecdhe - Disable ephemeral ECDH\n"); #endif BIO_printf(bio_err," -bugs - Turn on SSL bug compatibility\n"); BIO_printf(bio_err," -hack - workaround for early Netscape code\n"); BIO_printf(bio_err," -www - Respond to a 'GET /' with a status page\n"); BIO_printf(bio_err," -WWW - Respond to a 'GET / HTTP/1.0' with file ./\n"); BIO_printf(bio_err," -HTTP - Respond to a 'GET / HTTP/1.0' with file ./\n"); BIO_printf(bio_err," with the assumption it contains a complete HTTP response.\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); #endif BIO_printf(bio_err," -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n"); BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); #ifndef OPENSSL_NO_TLSEXT BIO_printf(bio_err," -servername host - servername for HostName TLS extension\n"); BIO_printf(bio_err," -servername_fatal - on mismatch send fatal alert (default warning alert)\n"); BIO_printf(bio_err," -cert2 arg - certificate file to use for servername\n"); BIO_printf(bio_err," (default is %s)\n",TEST_CERT2); BIO_printf(bio_err," -key2 arg - Private Key file to use for servername, in cert file if\n"); BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT2); BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n"); BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); # ifndef OPENSSL_NO_NEXTPROTONEG BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n"); # endif # ifndef OPENSSL_NO_SRTP BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); # endif #endif BIO_printf(bio_err," -keymatexport label - Export keying material using label\n"); BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n"); BIO_printf(bio_err," -status - respond to certificate status requests\n"); BIO_printf(bio_err," -status_verbose - enable status request verbose printout\n"); BIO_printf(bio_err," -status_timeout n - status request responder timeout\n"); BIO_printf(bio_err," -status_url URL - status request fallback URL\n"); } static int local_argc=0; static char **local_argv; #ifdef CHARSET_EBCDIC static int ebcdic_new(BIO *bi); static int ebcdic_free(BIO *a); static int ebcdic_read(BIO *b, char *out, int outl); static int ebcdic_write(BIO *b, const char *in, int inl); static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr); static int ebcdic_gets(BIO *bp, char *buf, int size); static int ebcdic_puts(BIO *bp, const char *str); #define BIO_TYPE_EBCDIC_FILTER (18|0x0200) static BIO_METHOD methods_ebcdic= { BIO_TYPE_EBCDIC_FILTER, "EBCDIC/ASCII filter", ebcdic_write, ebcdic_read, ebcdic_puts, ebcdic_gets, ebcdic_ctrl, ebcdic_new, ebcdic_free, }; typedef struct { size_t alloced; char buff[1]; } EBCDIC_OUTBUFF; BIO_METHOD *BIO_f_ebcdic_filter() { return(&methods_ebcdic); } static int ebcdic_new(BIO *bi) { EBCDIC_OUTBUFF *wbuf; wbuf = (EBCDIC_OUTBUFF *)OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + 1024); wbuf->alloced = 1024; wbuf->buff[0] = '\0'; bi->ptr=(char *)wbuf; bi->init=1; bi->flags=0; return(1); } static int ebcdic_free(BIO *a) { if (a == NULL) return(0); if (a->ptr != NULL) OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } static int ebcdic_read(BIO *b, char *out, int outl) { int ret=0; if (out == NULL || outl == 0) return(0); if (b->next_bio == NULL) return(0); ret=BIO_read(b->next_bio,out,outl); if (ret > 0) ascii2ebcdic(out,out,ret); return(ret); } static int ebcdic_write(BIO *b, const char *in, int inl) { EBCDIC_OUTBUFF *wbuf; int ret=0; int num; unsigned char n; if ((in == NULL) || (inl <= 0)) return(0); if (b->next_bio == NULL) return(0); wbuf=(EBCDIC_OUTBUFF *)b->ptr; if (inl > (num = wbuf->alloced)) { num = num + num; /* double the size */ if (num < inl) num = inl; OPENSSL_free(wbuf); wbuf=(EBCDIC_OUTBUFF *)OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + num); wbuf->alloced = num; wbuf->buff[0] = '\0'; b->ptr=(char *)wbuf; } ebcdic2ascii(wbuf->buff, in, inl); ret=BIO_write(b->next_bio, wbuf->buff, inl); return(ret); } static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret; if (b->next_bio == NULL) return(0); switch (cmd) { case BIO_CTRL_DUP: ret=0L; break; default: ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; } return(ret); } static int ebcdic_gets(BIO *bp, char *buf, int size) { int i, ret=0; if (bp->next_bio == NULL) return(0); /* return(BIO_gets(bp->next_bio,buf,size));*/ for (i=0; inext_bio == NULL) return(0); return ebcdic_write(bp, str, strlen(str)); } #endif #ifndef OPENSSL_NO_TLSEXT /* This is a context that we pass to callbacks */ typedef struct tlsextctx_st { char * servername; BIO * biodebug; int extension_error; } tlsextctx; static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { tlsextctx * p = (tlsextctx *) arg; const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); if (servername && p->biodebug) BIO_printf(p->biodebug,"Hostname in TLS extension: \"%s\"\n",servername); if (!p->servername) return SSL_TLSEXT_ERR_NOACK; if (servername) { if (strcasecmp(servername,p->servername)) return p->extension_error; if (ctx2) { BIO_printf(p->biodebug,"Switching server context.\n"); SSL_set_SSL_CTX(s,ctx2); } } return SSL_TLSEXT_ERR_OK; } /* Structure passed to cert status callback */ typedef struct tlsextstatusctx_st { /* Default responder to use */ char *host, *path, *port; int use_ssl; int timeout; BIO *err; int verbose; } tlsextstatusctx; static tlsextstatusctx tlscstatp = {NULL, NULL, NULL, 0, -1, NULL, 0}; /* Certificate Status callback. This is called when a client includes a * certificate status request extension. * * This is a simplified version. It examines certificates each time and * makes one OCSP responder query for each request. * * A full version would store details such as the OCSP certificate IDs and * minimise the number of OCSP responses by caching them until they were * considered "expired". */ static int cert_status_cb(SSL *s, void *arg) { tlsextstatusctx *srctx = arg; BIO *err = srctx->err; char *host, *port, *path; int use_ssl; unsigned char *rspder = NULL; int rspderlen; STACK_OF(OPENSSL_STRING) *aia = NULL; X509 *x = NULL; X509_STORE_CTX inctx; X509_OBJECT obj; OCSP_REQUEST *req = NULL; OCSP_RESPONSE *resp = NULL; OCSP_CERTID *id = NULL; STACK_OF(X509_EXTENSION) *exts; int ret = SSL_TLSEXT_ERR_NOACK; int i; #if 0 STACK_OF(OCSP_RESPID) *ids; SSL_get_tlsext_status_ids(s, &ids); BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids)); #endif if (srctx->verbose) BIO_puts(err, "cert_status: callback called\n"); /* Build up OCSP query from server certificate */ x = SSL_get_certificate(s); aia = X509_get1_ocsp(x); if (aia) { if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &host, &port, &path, &use_ssl)) { BIO_puts(err, "cert_status: can't parse AIA URL\n"); goto err; } if (srctx->verbose) BIO_printf(err, "cert_status: AIA URL: %s\n", sk_OPENSSL_STRING_value(aia, 0)); } else { if (!srctx->host) { BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n"); goto done; } host = srctx->host; path = srctx->path; port = srctx->port; use_ssl = srctx->use_ssl; } if (!X509_STORE_CTX_init(&inctx, SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), NULL, NULL)) goto err; if (X509_STORE_get_by_subject(&inctx,X509_LU_X509, X509_get_issuer_name(x),&obj) <= 0) { BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n"); X509_STORE_CTX_cleanup(&inctx); goto done; } req = OCSP_REQUEST_new(); if (!req) goto err; id = OCSP_cert_to_id(NULL, x, obj.data.x509); X509_free(obj.data.x509); X509_STORE_CTX_cleanup(&inctx); if (!id) goto err; if (!OCSP_request_add0_id(req, id)) goto err; id = NULL; /* Add any extensions to the request */ SSL_get_tlsext_status_exts(s, &exts); for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); if (!OCSP_REQUEST_add_ext(req, ext, -1)) goto err; } resp = process_responder(err, req, host, path, port, use_ssl, NULL, srctx->timeout); if (!resp) { BIO_puts(err, "cert_status: error querying responder\n"); goto done; } rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); if (rspderlen <= 0) goto err; SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); if (srctx->verbose) { BIO_puts(err, "cert_status: ocsp response sent:\n"); OCSP_RESPONSE_print(err, resp, 2); } ret = SSL_TLSEXT_ERR_OK; done: if (ret != SSL_TLSEXT_ERR_OK) ERR_print_errors(err); if (aia) { OPENSSL_free(host); OPENSSL_free(path); OPENSSL_free(port); X509_email_free(aia); } if (id) OCSP_CERTID_free(id); if (req) OCSP_REQUEST_free(req); if (resp) OCSP_RESPONSE_free(resp); return ret; err: ret = SSL_TLSEXT_ERR_ALERT_FATAL; goto done; } # ifndef OPENSSL_NO_NEXTPROTONEG /* This is the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { unsigned char *data; unsigned int len; } tlsextnextprotoctx; static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, void *arg) { tlsextnextprotoctx *next_proto = arg; *data = next_proto->data; *len = next_proto->len; return SSL_TLSEXT_ERR_OK; } # endif /* ndef OPENSSL_NO_NEXTPROTONEG */ #endif int MAIN(int, char **); #ifndef OPENSSL_NO_JPAKE static char *jpake_secret = NULL; #endif #ifndef OPENSSL_NO_SRP static srpsrvparm srp_callback_parm; #endif #ifndef OPENSSL_NO_SRTP static char *srtp_profiles = NULL; #endif int MAIN(int argc, char *argv[]) { X509_VERIFY_PARAM *vpm = NULL; int badarg = 0; short port=PORT; char *CApath=NULL,*CAfile=NULL; unsigned char *context = NULL; char *dhfile = NULL; #ifndef OPENSSL_NO_ECDH char *named_curve = NULL; #endif int badop=0,bugs=0; int ret=1; int off=0; int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0; int state=0; const SSL_METHOD *meth=NULL; int socket_type=SOCK_STREAM; ENGINE *e=NULL; char *inrand=NULL; int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; char *dpassarg = NULL, *dpass = NULL; int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; X509 *s_cert = NULL, *s_dcert = NULL; EVP_PKEY *s_key = NULL, *s_dkey = NULL; int no_cache = 0; #ifndef OPENSSL_NO_TLSEXT EVP_PKEY *s_key2 = NULL; X509 *s_cert2 = NULL; tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING}; # ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; tlsextnextprotoctx next_proto; # endif #endif #ifndef OPENSSL_NO_PSK /* by default do not send a PSK identity hint */ static char *psk_identity_hint=NULL; #endif #ifndef OPENSSL_NO_SRP char *srpuserseed = NULL; char *srp_verifier_file = NULL; #endif meth=SSLv23_server_method(); local_argc=argc; local_argv=argv; apps_startup(); #ifdef MONOLITH s_server_init(); #endif if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; verify_depth=0; #ifdef FIONBIO s_nbio=0; #endif s_nbio_test=0; argc--; argv++; while (argc >= 1) { if ((strcmp(*argv,"-port") == 0) || (strcmp(*argv,"-accept") == 0)) { if (--argc < 1) goto bad; if (!extract_port(*(++argv),&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-Verify") == 0) { s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_CLIENT_ONCE; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d, must return a certificate\n",verify_depth); } else if (strcmp(*argv,"-context") == 0) { if (--argc < 1) goto bad; context= (unsigned char *)*(++argv); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; s_cert_file= *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; s_cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; s_key_file= *(++argv); } else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; s_key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-dhparam") == 0) { if (--argc < 1) goto bad; dhfile = *(++argv); } #ifndef OPENSSL_NO_ECDH else if (strcmp(*argv,"-named_curve") == 0) { if (--argc < 1) goto bad; named_curve = *(++argv); } #endif else if (strcmp(*argv,"-dcertform") == 0) { if (--argc < 1) goto bad; s_dcert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-dcert") == 0) { if (--argc < 1) goto bad; s_dcert_file= *(++argv); } else if (strcmp(*argv,"-dkeyform") == 0) { if (--argc < 1) goto bad; s_dkey_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-dpass") == 0) { if (--argc < 1) goto bad; dpassarg = *(++argv); } else if (strcmp(*argv,"-dkey") == 0) { if (--argc < 1) goto bad; s_dkey_file= *(++argv); } else if (strcmp(*argv,"-nocert") == 0) { nocert=1; } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-no_cache") == 0) no_cache = 1; else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto bad; continue; } else if (strcmp(*argv,"-verify_return_error") == 0) verify_return_error = 1; else if (strcmp(*argv,"-serverpref") == 0) { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; } else if (strcmp(*argv,"-legacy_renegotiation") == 0) off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { s_nbio=1; } #endif else if (strcmp(*argv,"-nbio_test") == 0) { #ifdef FIONBIO s_nbio=1; #endif s_nbio_test=1; } else if (strcmp(*argv,"-debug") == 0) { s_debug=1; } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv,"-tlsextdebug") == 0) s_tlsextdebug=1; else if (strcmp(*argv,"-status") == 0) s_tlsextstatus=1; else if (strcmp(*argv,"-status_verbose") == 0) { s_tlsextstatus=1; tlscstatp.verbose = 1; } else if (!strcmp(*argv, "-status_timeout")) { s_tlsextstatus=1; if (--argc < 1) goto bad; tlscstatp.timeout = atoi(*(++argv)); } else if (!strcmp(*argv, "-status_url")) { s_tlsextstatus=1; if (--argc < 1) goto bad; if (!OCSP_parse_url(*(++argv), &tlscstatp.host, &tlscstatp.port, &tlscstatp.path, &tlscstatp.use_ssl)) { BIO_printf(bio_err, "Error parsing URL\n"); goto bad; } } #endif else if (strcmp(*argv,"-msg") == 0) { s_msg=1; } else if (strcmp(*argv,"-hack") == 0) { hack=1; } else if (strcmp(*argv,"-state") == 0) { state=1; } else if (strcmp(*argv,"-crlf") == 0) { s_crlf=1; } else if (strcmp(*argv,"-quiet") == 0) { s_quiet=1; } else if (strcmp(*argv,"-bugs") == 0) { bugs=1; } else if (strcmp(*argv,"-no_tmp_rsa") == 0) { no_tmp_rsa=1; } else if (strcmp(*argv,"-no_dhe") == 0) { no_dhe=1; } else if (strcmp(*argv,"-no_ecdhe") == 0) { no_ecdhe=1; } #ifndef OPENSSL_NO_PSK else if (strcmp(*argv,"-psk_hint") == 0) { if (--argc < 1) goto bad; psk_identity_hint= *(++argv); } else if (strcmp(*argv,"-psk") == 0) { size_t i; if (--argc < 1) goto bad; psk_key=*(++argv); for (i=0; i= 32) BIO_printf(bio_err, "warning: id_prefix is too long, only one new session will be possible\n"); else if(strlen(session_id_prefix) >= 16) BIO_printf(bio_err, "warning: id_prefix is too long if you use SSLv2\n"); if(!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { BIO_printf(bio_err,"error setting 'id_prefix'\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(bio_err,"id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx,1); if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL); if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); SSL_CTX_set_options(ctx,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (no_cache) SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); else SSL_CTX_sess_set_cache_size(ctx,128); #ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); #endif #if 0 if (cipher == NULL) cipher=getenv("SSL_CIPHER"); #endif #if 0 if (s_cert_file == NULL) { BIO_printf(bio_err,"You must specify a certificate file for the server to use\n"); goto end; } #endif if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"X509_load_verify_locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } if (vpm) SSL_CTX_set1_param(ctx, vpm); #ifndef OPENSSL_NO_TLSEXT if (s_cert2) { ctx2=SSL_CTX_new(meth); if (ctx2 == NULL) { ERR_print_errors(bio_err); goto end; } } if (ctx2) { BIO_printf(bio_s_out,"Setting secondary ctx parameters\n"); if (session_id_prefix) { if(strlen(session_id_prefix) >= 32) BIO_printf(bio_err, "warning: id_prefix is too long, only one new session will be possible\n"); else if(strlen(session_id_prefix) >= 16) BIO_printf(bio_err, "warning: id_prefix is too long if you use SSLv2\n"); if(!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) { BIO_printf(bio_err,"error setting 'id_prefix'\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(bio_err,"id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx2,1); if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL); if (hack) SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); SSL_CTX_set_options(ctx2,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx2, 1); if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback); if (no_cache) SSL_CTX_set_session_cache_mode(ctx2,SSL_SESS_CACHE_OFF); else SSL_CTX_sess_set_cache_size(ctx2,128); if ((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx2))) { ERR_print_errors(bio_err); } if (vpm) SSL_CTX_set1_param(ctx2, vpm); } # ifndef OPENSSL_NO_NEXTPROTONEG if (next_proto.data) SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto); # endif #endif #ifndef OPENSSL_NO_DH - if (!no_dhe) - { - DH *dh=NULL; + if (!no_dhe) { + DH *dh = NULL; if (dhfile) dh = load_dh_param(dhfile); else if (s_cert_file) dh = load_dh_param(s_cert_file); - if (dh != NULL) - { - BIO_printf(bio_s_out,"Setting temp DH parameters\n"); + if (dh != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); + } else { + BIO_printf(bio_s_out, "Using default temp DH parameters\n"); + dh = get_dh2048(); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; } - else - { - BIO_printf(bio_s_out,"Using default temp DH parameters\n"); - dh=get_dh512(); } (void)BIO_flush(bio_s_out); - SSL_CTX_set_tmp_dh(ctx,dh); -#ifndef OPENSSL_NO_TLSEXT - if (ctx2) - { - if (!dhfile) - { - DH *dh2=load_dh_param(s_cert_file2); - if (dh2 != NULL) - { - BIO_printf(bio_s_out,"Setting temp DH parameters\n"); + SSL_CTX_set_tmp_dh(ctx, dh); +# ifndef OPENSSL_NO_TLSEXT + if (ctx2) { + if (!dhfile) { + DH *dh2 = load_dh_param(s_cert_file2); + if (dh2 != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); (void)BIO_flush(bio_s_out); DH_free(dh); dh = dh2; } } - SSL_CTX_set_tmp_dh(ctx2,dh); + SSL_CTX_set_tmp_dh(ctx2, dh); } -#endif +# endif DH_free(dh); } #endif #ifndef OPENSSL_NO_ECDH if (!no_ecdhe) { EC_KEY *ecdh=NULL; if (named_curve) { int nid = OBJ_sn2nid(named_curve); if (nid == 0) { BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); goto end; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { BIO_printf(bio_err, "unable to create curve (%s)\n", named_curve); goto end; } } if (ecdh != NULL) { BIO_printf(bio_s_out,"Setting temp ECDH parameters\n"); } else { BIO_printf(bio_s_out,"Using default temp ECDH parameters\n"); ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh == NULL) { BIO_printf(bio_err, "unable to create curve (nistp256)\n"); goto end; } } (void)BIO_flush(bio_s_out); SSL_CTX_set_tmp_ecdh(ctx,ecdh); #ifndef OPENSSL_NO_TLSEXT if (ctx2) SSL_CTX_set_tmp_ecdh(ctx2,ecdh); #endif EC_KEY_free(ecdh); } #endif if (!set_cert_key_stuff(ctx, s_cert, s_key)) goto end; #ifndef OPENSSL_NO_TLSEXT if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2)) goto end; #endif if (s_dcert != NULL) { if (!set_cert_key_stuff(ctx, s_dcert, s_dkey)) goto end; } #ifndef OPENSSL_NO_RSA #if 1 if (!no_tmp_rsa) { SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb); #ifndef OPENSSL_NO_TLSEXT if (ctx2) SSL_CTX_set_tmp_rsa_callback(ctx2,tmp_rsa_cb); #endif } #else if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx)) { RSA *rsa; BIO_printf(bio_s_out,"Generating temp (512 bit) RSA key..."); BIO_flush(bio_s_out); rsa=RSA_generate_key(512,RSA_F4,NULL); if (!SSL_CTX_set_tmp_rsa(ctx,rsa)) { ERR_print_errors(bio_err); goto end; } #ifndef OPENSSL_NO_TLSEXT if (ctx2) { if (!SSL_CTX_set_tmp_rsa(ctx2,rsa)) { ERR_print_errors(bio_err); goto end; } } #endif RSA_free(rsa); BIO_printf(bio_s_out,"\n"); } #endif #endif #ifndef OPENSSL_NO_PSK #ifdef OPENSSL_NO_JPAKE if (psk_key != NULL) #else if (psk_key != NULL || jpake_secret) #endif { if (s_debug) BIO_printf(bio_s_out, "PSK key given or JPAKE in use, setting server callback\n"); SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); } if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { BIO_printf(bio_err,"error setting PSK identity hint to context\n"); ERR_print_errors(bio_err); goto end; } #endif if (cipher != NULL) { if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #ifndef OPENSSL_NO_TLSEXT if (ctx2 && !SSL_CTX_set_cipher_list(ctx2,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #endif } SSL_CTX_set_verify(ctx,s_server_verify,verify_callback); SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context, sizeof s_server_session_id_context); /* Set DTLS cookie generation and verification callbacks */ SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); #ifndef OPENSSL_NO_TLSEXT if (ctx2) { SSL_CTX_set_verify(ctx2,s_server_verify,verify_callback); SSL_CTX_set_session_id_context(ctx2,(void*)&s_server_session_id_context, sizeof s_server_session_id_context); tlsextcbp.biodebug = bio_s_out; SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } #endif #ifndef OPENSSL_NO_SRP if (srp_verifier_file != NULL) { srp_callback_parm.vb = SRP_VBASE_new(srpuserseed); srp_callback_parm.user = NULL; srp_callback_parm.login = NULL; if ((ret = SRP_VBASE_init(srp_callback_parm.vb, srp_verifier_file)) != SRP_NO_ERROR) { BIO_printf(bio_err, "Cannot initialize SRP verifier file \"%s\":ret=%d\n", srp_verifier_file, ret); goto end; } SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE,verify_callback); SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); } else #endif if (CAfile != NULL) { SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); #ifndef OPENSSL_NO_TLSEXT if (ctx2) SSL_CTX_set_client_CA_list(ctx2,SSL_load_client_CA_file(CAfile)); #endif } BIO_printf(bio_s_out,"ACCEPT\n"); (void)BIO_flush(bio_s_out); if (www) do_server(port,socket_type,&accept_socket,www_body, context); else do_server(port,socket_type,&accept_socket,sv_body, context); print_stats(bio_s_out,ctx); ret=0; end: if (ctx != NULL) SSL_CTX_free(ctx); if (s_cert) X509_free(s_cert); if (s_dcert) X509_free(s_dcert); if (s_key) EVP_PKEY_free(s_key); if (s_dkey) EVP_PKEY_free(s_dkey); if (pass) OPENSSL_free(pass); if (dpass) OPENSSL_free(dpass); if (vpm) X509_VERIFY_PARAM_free(vpm); #ifndef OPENSSL_NO_TLSEXT if (tlscstatp.host) OPENSSL_free(tlscstatp.host); if (tlscstatp.port) OPENSSL_free(tlscstatp.port); if (tlscstatp.path) OPENSSL_free(tlscstatp.path); if (ctx2 != NULL) SSL_CTX_free(ctx2); if (s_cert2) X509_free(s_cert2); if (s_key2) EVP_PKEY_free(s_key2); #endif if (bio_s_out != NULL) { BIO_free(bio_s_out); bio_s_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); } static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) { BIO_printf(bio,"%4ld items in the session cache\n", SSL_CTX_sess_number(ssl_ctx)); BIO_printf(bio,"%4ld client connects (SSL_connect())\n", SSL_CTX_sess_connect(ssl_ctx)); BIO_printf(bio,"%4ld client renegotiates (SSL_connect())\n", SSL_CTX_sess_connect_renegotiate(ssl_ctx)); BIO_printf(bio,"%4ld client connects that finished\n", SSL_CTX_sess_connect_good(ssl_ctx)); BIO_printf(bio,"%4ld server accepts (SSL_accept())\n", SSL_CTX_sess_accept(ssl_ctx)); BIO_printf(bio,"%4ld server renegotiates (SSL_accept())\n", SSL_CTX_sess_accept_renegotiate(ssl_ctx)); BIO_printf(bio,"%4ld server accepts that finished\n", SSL_CTX_sess_accept_good(ssl_ctx)); BIO_printf(bio,"%4ld session cache hits\n",SSL_CTX_sess_hits(ssl_ctx)); BIO_printf(bio,"%4ld session cache misses\n",SSL_CTX_sess_misses(ssl_ctx)); BIO_printf(bio,"%4ld session cache timeouts\n",SSL_CTX_sess_timeouts(ssl_ctx)); BIO_printf(bio,"%4ld callback cache hits\n",SSL_CTX_sess_cb_hits(ssl_ctx)); BIO_printf(bio,"%4ld cache full overflows (%ld allowed)\n", SSL_CTX_sess_cache_full(ssl_ctx), SSL_CTX_sess_get_cache_size(ssl_ctx)); } static int sv_body(char *hostname, int s, unsigned char *context) { char *buf=NULL; fd_set readfds; int ret=1,width; int k,i; unsigned long l; SSL *con=NULL; BIO *sbio; #ifndef OPENSSL_NO_KRB5 KSSL_CTX *kctx; #endif struct timeval timeout; #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) struct timeval tv; #else struct timeval *timeoutp; #endif if ((buf=OPENSSL_malloc(bufsize)) == NULL) { BIO_printf(bio_err,"out of memory\n"); goto err; } #ifdef FIONBIO if (s_nbio) { unsigned long sl=1; if (!s_quiet) BIO_printf(bio_err,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0) ERR_print_errors(bio_err); } #endif if (con == NULL) { con=SSL_new(ctx); #ifndef OPENSSL_NO_TLSEXT if (s_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } if (s_tlsextstatus) { SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); tlscstatp.err = bio_err; SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp); } #endif #ifndef OPENSSL_NO_KRB5 if ((kctx = kssl_ctx_new()) != NULL) { SSL_set0_kssl_ctx(con, kctx); kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC); kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB); } #endif /* OPENSSL_NO_KRB5 */ if(context) SSL_set_session_id_context(con, context, strlen((char *)context)); } SSL_clear(con); #if 0 #ifdef TLSEXT_TYPE_opaque_prf_input SSL_set_tlsext_opaque_prf_input(con, "Test server", 11); #endif #endif if (SSL_version(con) == DTLS1_VERSION) { sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if (socket_mtu) { if(socket_mtu < DTLS_get_link_min_mtu(con)) { BIO_printf(bio_err,"MTU too small. Must be at least %ld\n", DTLS_get_link_min_mtu(con)); ret = -1; BIO_free(sbio); goto err; } SSL_set_options(con, SSL_OP_NO_QUERY_MTU); if(!DTLS_set_link_mtu(con, socket_mtu)) { BIO_printf(bio_err, "Failed to set MTU\n"); ret = -1; BIO_free(sbio); goto err; } } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); /* turn on cookie exchange */ SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (s_nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } #ifndef OPENSSL_NO_JPAKE if(jpake_secret) jpake_server_auth(bio_s_out, sbio, jpake_secret); #endif SSL_set_bio(con,sbio,sbio); SSL_set_accept_state(con); /* SSL_set_fd(con,s); */ if (s_debug) { SSL_set_debug(con, 1); BIO_set_callback(SSL_get_rbio(con),bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con),(char *)bio_s_out); } if (s_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_s_out); } #ifndef OPENSSL_NO_TLSEXT if (s_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } #endif width=s+1; for (;;) { int read_from_terminal; int read_from_sslcon; read_from_terminal = 0; read_from_sslcon = SSL_pending(con); if (!read_from_sslcon) { FD_ZERO(&readfds); #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_BEOS_R5) openssl_fdset(fileno(stdin),&readfds); #endif openssl_fdset(s,&readfds); /* Note: under VMS with SOCKETSHR the second parameter is * currently of type (int *) whereas under other systems * it is (void *) if you don't have a cast it will choke * the compiler: if you do have a cast then you can either * go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Under DOS (non-djgpp) and Windows we can't select on stdin: only * on sockets. As a workaround we timeout the select every * second and check for any keypress. In a proper Windows * application we wouldn't do this because it is inefficient. */ tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,NULL,NULL,&tv); if((i < 0) || (!i && !_kbhit() ) )continue; if(_kbhit()) read_from_terminal = 1; #elif defined(OPENSSL_SYS_BEOS_R5) /* Under BeOS-R5 the situation is similar to DOS */ tv.tv_sec = 1; tv.tv_usec = 0; (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); i=select(width,(void *)&readfds,NULL,NULL,&tv); if ((i < 0) || (!i && read(fileno(stdin), buf, 0) < 0)) continue; if (read(fileno(stdin), buf, 0) >= 0) read_from_terminal = 1; (void)fcntl(fileno(stdin), F_SETFL, 0); #else if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; i=select(width,(void *)&readfds,NULL,NULL,timeoutp); if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err,"TIMEOUT occured\n"); } if (i <= 0) continue; if (FD_ISSET(fileno(stdin),&readfds)) read_from_terminal = 1; #endif if (FD_ISSET(s,&readfds)) read_from_sslcon = 1; } if (read_from_terminal) { if (s_crlf) { int j, lf_num; i=raw_read_stdin(buf, bufsize/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (buf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { buf[j+lf_num] = buf[j]; if (buf[j] == '\n') { lf_num--; i++; buf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=raw_read_stdin(buf,bufsize); if (!s_quiet) { if ((i <= 0) || (buf[0] == 'Q')) { BIO_printf(bio_s_out,"DONE\n"); SHUTDOWN(s); close_accept_socket(); ret= -11; goto err; } if ((i <= 0) || (buf[0] == 'q')) { BIO_printf(bio_s_out,"DONE\n"); if (SSL_version(con) != DTLS1_VERSION) SHUTDOWN(s); /* close_accept_socket(); ret= -11;*/ goto err; } #ifndef OPENSSL_NO_HEARTBEATS if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) { BIO_printf(bio_err,"HEARTBEATING\n"); SSL_heartbeat(con); i=0; continue; } #endif if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) { SSL_renegotiate(con); i=SSL_do_handshake(con); printf("SSL_do_handshake -> %d\n",i); i=0; /*13; */ continue; /* strcpy(buf,"server side RE-NEGOTIATE\n"); */ } if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) { SSL_set_verify(con, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,NULL); SSL_renegotiate(con); i=SSL_do_handshake(con); printf("SSL_do_handshake -> %d\n",i); i=0; /* 13; */ continue; /* strcpy(buf,"server side RE-NEGOTIATE asking for client cert\n"); */ } if (buf[0] == 'P') { static const char *str="Lets print some clear text\n"; BIO_write(SSL_get_wbio(con),str,strlen(str)); } if (buf[0] == 'S') { print_stats(bio_s_out,SSL_get_SSL_CTX(con)); } } #ifdef CHARSET_EBCDIC ebcdic2ascii(buf,buf,i); #endif l=k=0; for (;;) { /* should do a select for the write */ #ifdef RENEG { static count=0; if (++count == 100) { count=0; SSL_renegotiate(con); } } #endif k=SSL_write(con,&(buf[l]),(unsigned int)i); #ifndef OPENSSL_NO_SRP while (SSL_get_error(con,k) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP renego during write\n"); srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else BIO_printf(bio_s_out,"LOOKUP not successful\n"); k=SSL_write(con,&(buf[l]),(unsigned int)i); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_s_out,"Write BLOCK\n"); break; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: BIO_printf(bio_s_out,"ERROR\n"); ERR_print_errors(bio_err); ret=1; goto err; /* break; */ case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_s_out,"DONE\n"); ret=1; goto err; } l+=k; i-=k; if (i <= 0) break; } } if (read_from_sslcon) { if (!SSL_is_init_finished(con)) { i=init_ssl_connection(con); if (i < 0) { ret=0; goto err; } else if (i == 0) { ret=1; goto err; } } else { again: i=SSL_read(con,(char *)buf,bufsize); #ifndef OPENSSL_NO_SRP while (SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP renego during read\n"); srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else BIO_printf(bio_s_out,"LOOKUP not successful\n"); i=SSL_read(con,(char *)buf,bufsize); } #endif switch (SSL_get_error(con,i)) { case SSL_ERROR_NONE: #ifdef CHARSET_EBCDIC ascii2ebcdic(buf,buf,i); #endif raw_write_stdout(buf, (unsigned int)i); if (SSL_pending(con)) goto again; break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: BIO_printf(bio_s_out,"Read BLOCK\n"); break; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: BIO_printf(bio_s_out,"ERROR\n"); ERR_print_errors(bio_err); ret=1; goto err; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_s_out,"DONE\n"); ret=1; goto err; } } } } err: if (con != NULL) { BIO_printf(bio_s_out,"shutting down SSL\n"); #if 1 SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(con); #endif SSL_free(con); } BIO_printf(bio_s_out,"CONNECTION CLOSED\n"); if (buf != NULL) { OPENSSL_cleanse(buf,bufsize); OPENSSL_free(buf); } if (ret >= 0) BIO_printf(bio_s_out,"ACCEPT\n"); return(ret); } static void close_accept_socket(void) { BIO_printf(bio_err,"shutdown accept socket\n"); if (accept_socket >= 0) { SHUTDOWN2(accept_socket); } } static int init_ssl_connection(SSL *con) { int i; const char *str; X509 *peer; long verify_error; MS_STATIC char buf[BUFSIZ]; #ifndef OPENSSL_NO_KRB5 char *client_princ; #endif #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) const unsigned char *next_proto_neg; unsigned next_proto_neg_len; #endif unsigned char *exportedkeymat; i=SSL_accept(con); #ifndef OPENSSL_NO_SRP while (i <= 0 && SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP during accept %s\n",srp_callback_parm.login); srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else BIO_printf(bio_s_out,"LOOKUP not successful\n"); i=SSL_accept(con); } #endif if (i <= 0) { if (BIO_sock_should_retry(i)) { BIO_printf(bio_s_out,"DELAY\n"); return(1); } BIO_printf(bio_err,"ERROR\n"); verify_error=SSL_get_verify_result(con); if (verify_error != X509_V_OK) { BIO_printf(bio_err,"verify error:%s\n", X509_verify_cert_error_string(verify_error)); } else ERR_print_errors(bio_err); return(0); } PEM_write_bio_SSL_SESSION(bio_s_out,SSL_get_session(con)); peer=SSL_get_peer_certificate(con); if (peer != NULL) { BIO_printf(bio_s_out,"Client certificate\n"); PEM_write_bio_X509(bio_s_out,peer); X509_NAME_oneline(X509_get_subject_name(peer),buf,sizeof buf); BIO_printf(bio_s_out,"subject=%s\n",buf); X509_NAME_oneline(X509_get_issuer_name(peer),buf,sizeof buf); BIO_printf(bio_s_out,"issuer=%s\n",buf); X509_free(peer); } if (SSL_get_shared_ciphers(con,buf,sizeof buf) != NULL) BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf); str=SSL_CIPHER_get_name(SSL_get_current_cipher(con)); BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)"); #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); if (next_proto_neg) { BIO_printf(bio_s_out,"NEXTPROTO is "); BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len); BIO_printf(bio_s_out, "\n"); } #endif #ifndef OPENSSL_NO_SRTP { SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(con); if(srtp_profile) BIO_printf(bio_s_out,"SRTP Extension negotiated, profile=%s\n", srtp_profile->name); } #endif if (SSL_cache_hit(con)) BIO_printf(bio_s_out,"Reused session-id\n"); if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) & TLS1_FLAGS_TLS_PADDING_BUG) BIO_printf(bio_s_out, "Peer has incorrect TLSv1 block padding\n"); #ifndef OPENSSL_NO_KRB5 client_princ = kssl_ctx_get0_client_princ(SSL_get0_kssl_ctx(con)); if (client_princ != NULL) { BIO_printf(bio_s_out,"Kerberos peer principal is %s\n", client_princ); } #endif /* OPENSSL_NO_KRB5 */ BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); if (keymatexportlabel != NULL) { BIO_printf(bio_s_out, "Keying material exporter:\n"); BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen); exportedkeymat = OPENSSL_malloc(keymatexportlen); if (exportedkeymat != NULL) { if (!SSL_export_keying_material(con, exportedkeymat, keymatexportlen, keymatexportlabel, strlen(keymatexportlabel), NULL, 0, 0)) { BIO_printf(bio_s_out, " Error\n"); } else { BIO_printf(bio_s_out, " Keying material: "); for (i=0; iinfo); else BIO_printf(bio_s_out,"LOOKUP not successful\n"); i=SSL_accept(con); } #endif switch (SSL_get_error(con,i)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: continue; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: case SSL_ERROR_ZERO_RETURN: ret=1; goto err; /* break; */ } SSL_renegotiate(con); SSL_write(con,NULL,0); } i=BIO_gets(io,buf,bufsize-1); if (i < 0) /* error */ { if (!BIO_should_retry(io)) { if (!s_quiet) ERR_print_errors(bio_err); goto err; } else { BIO_printf(bio_s_out,"read R BLOCK\n"); #if defined(OPENSSL_SYS_NETWARE) delay(1000); #elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__) sleep(1); #endif continue; } } else if (i == 0) /* end of input */ { ret=1; goto end; } /* else we have data */ if ( ((www == 1) && (strncmp("GET ",buf,4) == 0)) || ((www == 2) && (strncmp("GET /stats ",buf,10) == 0))) { char *p; X509 *peer; STACK_OF(SSL_CIPHER) *sk; static const char *space=" "; BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); BIO_puts(io,"\n"); BIO_puts(io,"
\n");
 /*			BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
 			BIO_puts(io,"\n");
 			for (i=0; i\r\n\r\n");
 			break;
 			}
 		else if ((www == 2 || www == 3)
                          && (strncmp("GET /",buf,5) == 0))
 			{
 			BIO *file;
 			char *p,*e;
 			static const char *text="HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
 
 			/* skip the '/' */
 			p= &(buf[5]);
 
 			dot = 1;
 			for (e=p; *e != '\0'; e++)
 				{
 				if (e[0] == ' ')
 					break;
 
 				switch (dot)
 					{
 				case 1:
 					dot = (e[0] == '.') ? 2 : 0;
 					break;
 				case 2:
 					dot = (e[0] == '.') ? 3 : 0;
 					break;
 				case 3:
 					dot = (e[0] == '/') ? -1 : 0;
 					break;
 					}
 				if (dot == 0)
 					dot = (e[0] == '/') ? 1 : 0;
 				}
 			dot = (dot == 3) || (dot == -1); /* filename contains ".." component */
 
 			if (*e == '\0')
 				{
 				BIO_puts(io,text);
 				BIO_printf(io,"'%s' is an invalid file name\r\n",p);
 				break;
 				}
 			*e='\0';
 
 			if (dot)
 				{
 				BIO_puts(io,text);
 				BIO_printf(io,"'%s' contains '..' reference\r\n",p);
 				break;
 				}
 
 			if (*p == '/')
 				{
 				BIO_puts(io,text);
 				BIO_printf(io,"'%s' is an invalid path\r\n",p);
 				break;
 				}
 
 #if 0
 			/* append if a directory lookup */
 			if (e[-1] == '/')
 				strcat(p,"index.html");
 #endif
 
 			/* if a directory, do the index thang */
 			if (app_isdir(p)>0)
 				{
 #if 0 /* must check buffer size */
 				strcat(p,"/index.html");
 #else
 				BIO_puts(io,text);
 				BIO_printf(io,"'%s' is a directory\r\n",p);
 				break;
 #endif
 				}
 
 			if ((file=BIO_new_file(p,"r")) == NULL)
 				{
 				BIO_puts(io,text);
 				BIO_printf(io,"Error opening '%s'\r\n",p);
 				ERR_print_errors(io);
 				break;
 				}
 
 			if (!s_quiet)
 				BIO_printf(bio_err,"FILE:%s\n",p);
 
                         if (www == 2)
                                 {
                                 i=strlen(p);
                                 if (	((i > 5) && (strcmp(&(p[i-5]),".html") == 0)) ||
                                         ((i > 4) && (strcmp(&(p[i-4]),".php") == 0)) ||
                                         ((i > 4) && (strcmp(&(p[i-4]),".htm") == 0)))
                                         BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
                                 else
                                         BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
                                 }
 			/* send the file */
 			for (;;)
 				{
 				i=BIO_read(file,buf,bufsize);
 				if (i <= 0) break;
 
 #ifdef RENEG
 				total_bytes+=i;
 				fprintf(stderr,"%d\n",i);
 				if (total_bytes > 3*1024)
 					{
 					total_bytes=0;
 					fprintf(stderr,"RENEGOTIATE\n");
 					SSL_renegotiate(con);
 					}
 #endif
 
 				for (j=0; j= 0)
 		BIO_printf(bio_s_out,"ACCEPT\n");
 
 	if (buf != NULL) OPENSSL_free(buf);
 	if (io != NULL) BIO_free_all(io);
 /*	if (ssl_bio != NULL) BIO_free(ssl_bio);*/
 	return(ret);
 	}
 
 #ifndef OPENSSL_NO_RSA
 static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
 	{
 	BIGNUM *bn = NULL;
 	static RSA *rsa_tmp=NULL;
 
 	if (!rsa_tmp && ((bn = BN_new()) == NULL))
 		BIO_printf(bio_err,"Allocation error in generating RSA key\n");
 	if (!rsa_tmp && bn)
 		{
 		if (!s_quiet)
 			{
 			BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
 			(void)BIO_flush(bio_err);
 			}
 		if(!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) ||
 				!RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL))
 			{
 			if(rsa_tmp) RSA_free(rsa_tmp);
 			rsa_tmp = NULL;
 			}
 		if (!s_quiet)
 			{
 			BIO_printf(bio_err,"\n");
 			(void)BIO_flush(bio_err);
 			}
 		BN_free(bn);
 		}
 	return(rsa_tmp);
 	}
 #endif
 
 #define MAX_SESSION_ID_ATTEMPTS 10
 static int generate_session_id(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len)
 	{
 	unsigned int count = 0;
 	do	{
 		RAND_pseudo_bytes(id, *id_len);
 		/* Prefix the session_id with the required prefix. NB: If our
 		 * prefix is too long, clip it - but there will be worse effects
 		 * anyway, eg. the server could only possibly create 1 session
 		 * ID (ie. the prefix!) so all future session negotiations will
 		 * fail due to conflicts. */
 		memcpy(id, session_id_prefix,
 			(strlen(session_id_prefix) < *id_len) ?
 			strlen(session_id_prefix) : *id_len);
 		}
 	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
 		(++count < MAX_SESSION_ID_ATTEMPTS));
 	if(count >= MAX_SESSION_ID_ATTEMPTS)
 		return 0;
 	return 1;
 	}
Index: releng/10.1/crypto/openssl/crypto/bio/bio_lib.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/bio/bio_lib.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/bio/bio_lib.c	(revision 284295)
@@ -1,602 +1,604 @@
 /* crypto/bio/bio_lib.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 
 BIO *BIO_new(BIO_METHOD *method)
 	{
 	BIO *ret=NULL;
 
 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
 	if (ret == NULL)
 		{
 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
 		return(NULL);
 		}
 	if (!BIO_set(ret,method))
 		{
 		OPENSSL_free(ret);
 		ret=NULL;
 		}
 	return(ret);
 	}
 
 int BIO_set(BIO *bio, BIO_METHOD *method)
 	{
 	bio->method=method;
 	bio->callback=NULL;
 	bio->cb_arg=NULL;
 	bio->init=0;
 	bio->shutdown=1;
 	bio->flags=0;
 	bio->retry_reason=0;
 	bio->num=0;
 	bio->ptr=NULL;
 	bio->prev_bio=NULL;
 	bio->next_bio=NULL;
 	bio->references=1;
 	bio->num_read=0L;
 	bio->num_write=0L;
 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
 	if (method->create != NULL)
 		if (!method->create(bio))
 			{
 			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
 					&bio->ex_data);
 			return(0);
 			}
 	return(1);
 	}
 
 int BIO_free(BIO *a)
 	{
 	int i;
 
 	if (a == NULL) return(0);
 
 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
 #ifdef REF_PRINT
 	REF_PRINT("BIO",a);
 #endif
 	if (i > 0) return(1);
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"BIO_free, bad reference count\n");
 		abort();
 		}
 #endif
 	if ((a->callback != NULL) &&
 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
 			return(i);
 
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
 
 	if ((a->method != NULL) && (a->method->destroy != NULL))
 		a->method->destroy(a);
 	OPENSSL_free(a);
 	return(1);
 	}
 
 void BIO_vfree(BIO *a)
     { BIO_free(a); }
 
 void BIO_clear_flags(BIO *b, int flags)
 	{
 	b->flags &= ~flags;
 	}
 
 int	BIO_test_flags(const BIO *b, int flags)
 	{
 	return (b->flags & flags);
 	}
 
 void	BIO_set_flags(BIO *b, int flags)
 	{
 	b->flags |= flags;
 	}
 
 long (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, long,long)
 	{
 	return b->callback;
 	}
 
 void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, long,long))
 	{
 	b->callback = cb;
 	}
 
 void BIO_set_callback_arg(BIO *b, char *arg)
 	{
 	b->cb_arg = arg;
 	}
 
 char * BIO_get_callback_arg(const BIO *b)
 	{
 	return b->cb_arg;
 	}
 
 const char * BIO_method_name(const BIO *b)
 	{
 	return b->method->name;
 	}
 
 int BIO_method_type(const BIO *b)
 	{
 	return b->method->type;
 	}
 
 
 int BIO_read(BIO *b, void *out, int outl)
 	{
 	int i;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
 		{
 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	cb=b->callback;
 	if ((cb != NULL) &&
 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
 			return(i);
 
 	if (!b->init)
 		{
 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
 		return(-2);
 		}
 
 	i=b->method->bread(b,out,outl);
 
 	if (i > 0) b->num_read+=(unsigned long)i;
 
 	if (cb != NULL)
 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
 			0L,(long)i);
 	return(i);
 	}
 
 int BIO_write(BIO *b, const void *in, int inl)
 	{
 	int i;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if (b == NULL)
 		return(0);
 
 	cb=b->callback;
 	if ((b->method == NULL) || (b->method->bwrite == NULL))
 		{
 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	if ((cb != NULL) &&
 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
 			return(i);
 
 	if (!b->init)
 		{
 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
 		return(-2);
 		}
 
 	i=b->method->bwrite(b,in,inl);
 
 	if (i > 0) b->num_write+=(unsigned long)i;
 
 	if (cb != NULL)
 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
 			0L,(long)i);
 	return(i);
 	}
 
 int BIO_puts(BIO *b, const char *in)
 	{
 	int i;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
 		{
 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	cb=b->callback;
 
 	if ((cb != NULL) &&
 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
 			return(i);
 
 	if (!b->init)
 		{
 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
 		return(-2);
 		}
 
 	i=b->method->bputs(b,in);
 
 	if (i > 0) b->num_write+=(unsigned long)i;
 
 	if (cb != NULL)
 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
 			0L,(long)i);
 	return(i);
 	}
 
 int BIO_gets(BIO *b, char *in, int inl)
 	{
 	int i;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
 		{
 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	cb=b->callback;
 
 	if ((cb != NULL) &&
 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
 			return(i);
 
 	if (!b->init)
 		{
 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
 		return(-2);
 		}
 
 	i=b->method->bgets(b,in,inl);
 
 	if (cb != NULL)
 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
 			0L,(long)i);
 	return(i);
 	}
 
 int BIO_indent(BIO *b,int indent,int max)
 	{
 	if(indent < 0)
 		indent=0;
 	if(indent > max)
 		indent=max;
 	while(indent--)
 		if(BIO_puts(b," ") != 1)
 			return 0;
 	return 1;
 	}
 
 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
 	{
 	int i;
 
 	i=iarg;
 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
 	}
 
 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
 	{
 	char *p=NULL;
 
 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
 		return(NULL);
 	else
 		return(p);
 	}
 
 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
 	{
 	long ret;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if (b == NULL) return(0);
 
 	if ((b->method == NULL) || (b->method->ctrl == NULL))
 		{
 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	cb=b->callback;
 
 	if ((cb != NULL) &&
 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
 		return(ret);
 
 	ret=b->method->ctrl(b,cmd,larg,parg);
 
 	if (cb != NULL)
 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
 			larg,ret);
 	return(ret);
 	}
 
 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
 	{
 	long ret;
 	long (*cb)(BIO *,int,const char *,int,long,long);
 
 	if (b == NULL) return(0);
 
 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
 		{
 		BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD);
 		return(-2);
 		}
 
 	cb=b->callback;
 
 	if ((cb != NULL) &&
 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
 		return(ret);
 
 	ret=b->method->callback_ctrl(b,cmd,fp);
 
 	if (cb != NULL)
 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
 			0,ret);
 	return(ret);
 	}
 
 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
  * do; but those macros have inappropriate return type, and for interfacing
  * from other programming languages, C macros aren't much of a help anyway. */
 size_t BIO_ctrl_pending(BIO *bio)
 	{
 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
 	}
 
 size_t BIO_ctrl_wpending(BIO *bio)
 	{
 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
 	}
 
 
 /* put the 'bio' on the end of b's list of operators */
 BIO *BIO_push(BIO *b, BIO *bio)
 	{
 	BIO *lb;
 
 	if (b == NULL) return(bio);
 	lb=b;
 	while (lb->next_bio != NULL)
 		lb=lb->next_bio;
 	lb->next_bio=bio;
 	if (bio != NULL)
 		bio->prev_bio=lb;
 	/* called to do internal processing */
 	BIO_ctrl(b,BIO_CTRL_PUSH,0,lb);
 	return(b);
 	}
 
 /* Remove the first and return the rest */
 BIO *BIO_pop(BIO *b)
 	{
 	BIO *ret;
 
 	if (b == NULL) return(NULL);
 	ret=b->next_bio;
 
 	BIO_ctrl(b,BIO_CTRL_POP,0,b);
 
 	if (b->prev_bio != NULL)
 		b->prev_bio->next_bio=b->next_bio;
 	if (b->next_bio != NULL)
 		b->next_bio->prev_bio=b->prev_bio;
 
 	b->next_bio=NULL;
 	b->prev_bio=NULL;
 	return(ret);
 	}
 
 BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
 	{
 	BIO *b,*last;
 
 	b=last=bio;
 	for (;;)
 		{
 		if (!BIO_should_retry(b)) break;
 		last=b;
 		b=b->next_bio;
 		if (b == NULL) break;
 		}
 	if (reason != NULL) *reason=last->retry_reason;
 	return(last);
 	}
 
 int BIO_get_retry_reason(BIO *bio)
 	{
 	return(bio->retry_reason);
 	}
 
 BIO *BIO_find_type(BIO *bio, int type)
 	{
 	int mt,mask;
 
 	if(!bio) return NULL;
 	mask=type&0xff;
 	do	{
 		if (bio->method != NULL)
 			{
 			mt=bio->method->type;
 
 			if (!mask)
 				{
 				if (mt & type) return(bio);
 				}
 			else if (mt == type)
 				return(bio);
 			}
 		bio=bio->next_bio;
 		} while (bio != NULL);
 	return(NULL);
 	}
 
 BIO *BIO_next(BIO *b)
 	{
 	if(!b) return NULL;
 	return b->next_bio;
 	}
 
 void BIO_free_all(BIO *bio)
 	{
 	BIO *b;
 	int ref;
 
 	while (bio != NULL)
 		{
 		b=bio;
 		ref=b->references;
 		bio=bio->next_bio;
 		BIO_free(b);
 		/* Since ref count > 1, don't free anyone else. */
 		if (ref > 1) break;
 		}
 	}
 
 BIO *BIO_dup_chain(BIO *in)
 	{
 	BIO *ret=NULL,*eoc=NULL,*bio,*new_bio;
 
 	for (bio=in; bio != NULL; bio=bio->next_bio)
 		{
 		if ((new_bio=BIO_new(bio->method)) == NULL) goto err;
 		new_bio->callback=bio->callback;
 		new_bio->cb_arg=bio->cb_arg;
 		new_bio->init=bio->init;
 		new_bio->shutdown=bio->shutdown;
 		new_bio->flags=bio->flags;
 
 		/* This will let SSL_s_sock() work with stdin/stdout */
 		new_bio->num=bio->num;
 
 		if (!BIO_dup_state(bio,(char *)new_bio))
 			{
 			BIO_free(new_bio);
 			goto err;
 			}
 
 		/* copy app data */
 		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
-					&bio->ex_data))
+                                &bio->ex_data)) {
+            BIO_free(new_bio);
 			goto err;
+        }
 
 		if (ret == NULL)
 			{
 			eoc=new_bio;
 			ret=eoc;
 			}
 		else
 			{
 			BIO_push(eoc,new_bio);
 			eoc=new_bio;
 			}
 		}
 	return(ret);
 err:
-	if (ret != NULL)
-		BIO_free(ret);
+	BIO_free_all(ret);
+
 	return(NULL);	
 	}
 
 void BIO_copy_next_retry(BIO *b)
 	{
 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
 	b->retry_reason=b->next_bio->retry_reason;
 	}
 
 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
 				new_func, dup_func, free_func);
 	}
 
 int BIO_set_ex_data(BIO *bio, int idx, void *data)
 	{
 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
 	}
 
 void *BIO_get_ex_data(BIO *bio, int idx)
 	{
 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
 	}
 
 unsigned long BIO_number_read(BIO *bio)
 {
 	if(bio) return bio->num_read;
 	return 0;
 }
 
 unsigned long BIO_number_written(BIO *bio)
 {
 	if(bio) return bio->num_write;
 	return 0;
 }
 
 IMPLEMENT_STACK_OF(BIO)
Index: releng/10.1/crypto/openssl/crypto/bn/bn_gf2m.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/bn/bn_gf2m.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/bn/bn_gf2m.c	(revision 284295)
@@ -1,1113 +1,1119 @@
 /* crypto/bn/bn_gf2m.c */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
  * to the OpenSSL project.
  *
  * The ECC Code is licensed pursuant to the OpenSSL open source
  * license provided below.
  *
  * In addition, Sun covenants to all licensees who provide a reciprocal
  * covenant with respect to their own patents if any, not to sue under
  * current and future patent claims necessarily infringed by the making,
  * using, practicing, selling, offering for sale and/or otherwise
  * disposing of the ECC Code as delivered hereunder (or portions thereof),
  * provided that such covenant shall not apply:
  *  1) for code that a licensee deletes from the ECC Code;
  *  2) separates from the ECC Code; or
  *  3) for infringements caused by:
  *       i) the modification of the ECC Code or
  *      ii) the combination of the ECC Code with other software or
  *          devices where such combination causes the infringement.
  *
  * The software is originally written by Sheueling Chang Shantz and
  * Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 
 /* NOTE: This file is licensed pursuant to the OpenSSL license below
  * and may be modified; but after modifications, the above covenant
  * may no longer apply!  In such cases, the corresponding paragraph
  * ["In addition, Sun covenants ... causes the infringement."] and
  * this note can be edited out; but please keep the Sun copyright
  * notice and attribution. */
 
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
 #ifndef OPENSSL_NO_EC2M
 
 /* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should fail. */
 #define MAX_ITERATIONS 50
 
 static const BN_ULONG SQR_tb[16] =
   {     0,     1,     4,     5,    16,    17,    20,    21,
        64,    65,    68,    69,    80,    81,    84,    85 };
 /* Platform-specific macros to accelerate squaring. */
 #if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
 #define SQR1(w) \
     SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
     SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
     SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
     SQR_tb[(w) >> 36 & 0xF] <<  8 | SQR_tb[(w) >> 32 & 0xF]
 #define SQR0(w) \
     SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
     SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
     SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
     SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
 #endif
 #ifdef THIRTY_TWO_BIT
 #define SQR1(w) \
     SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \
     SQR_tb[(w) >> 20 & 0xF] <<  8 | SQR_tb[(w) >> 16 & 0xF]
 #define SQR0(w) \
     SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
     SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
 #endif
 
 #if !defined(OPENSSL_BN_ASM_GF2m)
 /* Product of two polynomials a, b each with degree < BN_BITS2 - 1,
  * result is a polynomial r with degree < 2 * BN_BITS - 1
  * The caller MUST ensure that the variables have the right amount
  * of space allocated.
  */
 #ifdef THIRTY_TWO_BIT
 static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
 	{
 	register BN_ULONG h, l, s;
 	BN_ULONG tab[8], top2b = a >> 30; 
 	register BN_ULONG a1, a2, a4;
 
 	a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
 
 	tab[0] =  0; tab[1] = a1;    tab[2] = a2;    tab[3] = a1^a2;
 	tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
 
 	s = tab[b       & 0x7]; l  = s;
 	s = tab[b >>  3 & 0x7]; l ^= s <<  3; h  = s >> 29;
 	s = tab[b >>  6 & 0x7]; l ^= s <<  6; h ^= s >> 26;
 	s = tab[b >>  9 & 0x7]; l ^= s <<  9; h ^= s >> 23;
 	s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
 	s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
 	s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
 	s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
 	s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >>  8;
 	s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >>  5;
 	s = tab[b >> 30      ]; l ^= s << 30; h ^= s >>  2;
 
 	/* compensate for the top two bits of a */
 
 	if (top2b & 01) { l ^= b << 30; h ^= b >> 2; } 
 	if (top2b & 02) { l ^= b << 31; h ^= b >> 1; } 
 
 	*r1 = h; *r0 = l;
 	} 
 #endif
 #if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
 static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
 	{
 	register BN_ULONG h, l, s;
 	BN_ULONG tab[16], top3b = a >> 61;
 	register BN_ULONG a1, a2, a4, a8;
 
 	a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1; a4 = a2 << 1; a8 = a4 << 1;
 
 	tab[ 0] = 0;     tab[ 1] = a1;       tab[ 2] = a2;       tab[ 3] = a1^a2;
 	tab[ 4] = a4;    tab[ 5] = a1^a4;    tab[ 6] = a2^a4;    tab[ 7] = a1^a2^a4;
 	tab[ 8] = a8;    tab[ 9] = a1^a8;    tab[10] = a2^a8;    tab[11] = a1^a2^a8;
 	tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
 
 	s = tab[b       & 0xF]; l  = s;
 	s = tab[b >>  4 & 0xF]; l ^= s <<  4; h  = s >> 60;
 	s = tab[b >>  8 & 0xF]; l ^= s <<  8; h ^= s >> 56;
 	s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
 	s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
 	s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
 	s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
 	s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
 	s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
 	s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
 	s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
 	s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
 	s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
 	s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
 	s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >>  8;
 	s = tab[b >> 60      ]; l ^= s << 60; h ^= s >>  4;
 
 	/* compensate for the top three bits of a */
 
 	if (top3b & 01) { l ^= b << 61; h ^= b >> 3; } 
 	if (top3b & 02) { l ^= b << 62; h ^= b >> 2; } 
 	if (top3b & 04) { l ^= b << 63; h ^= b >> 1; } 
 
 	*r1 = h; *r0 = l;
 	} 
 #endif
 
 /* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1,
  * result is a polynomial r with degree < 4 * BN_BITS2 - 1
  * The caller MUST ensure that the variables have the right amount
  * of space allocated.
  */
 static void bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0, const BN_ULONG b1, const BN_ULONG b0)
 	{
 	BN_ULONG m1, m0;
 	/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
 	bn_GF2m_mul_1x1(r+3, r+2, a1, b1);
 	bn_GF2m_mul_1x1(r+1, r, a0, b0);
 	bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
 	/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
 	r[2] ^= m1 ^ r[1] ^ r[3];  /* h0 ^= m1 ^ l1 ^ h1; */
 	r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0;  /* l1 ^= l0 ^ h0 ^ m0; */
 	}
 #else
 void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, BN_ULONG b0);
 #endif 
 
 /* Add polynomials a and b and store result in r; r could be a or b, a and b 
  * could be equal; r is the bitwise XOR of a and b.
  */
 int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
 	{
 	int i;
 	const BIGNUM *at, *bt;
 
 	bn_check_top(a);
 	bn_check_top(b);
 
 	if (a->top < b->top) { at = b; bt = a; }
 	else { at = a; bt = b; }
 
 	if(bn_wexpand(r, at->top) == NULL)
 		return 0;
 
 	for (i = 0; i < bt->top; i++)
 		{
 		r->d[i] = at->d[i] ^ bt->d[i];
 		}
 	for (; i < at->top; i++)
 		{
 		r->d[i] = at->d[i];
 		}
 	
 	r->top = at->top;
 	bn_correct_top(r);
 	
 	return 1;
 	}
 
 
 /* Some functions allow for representation of the irreducible polynomials
  * as an int[], say p.  The irreducible f(t) is then of the form:
  *     t^p[0] + t^p[1] + ... + t^p[k]
  * where m = p[0] > p[1] > ... > p[k] = 0.
  */
 
 
 /* Performs modular reduction of a and store result in r.  r could be a. */
 int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
 	{
 	int j, k;
 	int n, dN, d0, d1;
 	BN_ULONG zz, *z;
 
 	bn_check_top(a);
 
 	if (!p[0])
 		{
 		/* reduction mod 1 => return 0 */
 		BN_zero(r);
 		return 1;
 		}
 
 	/* Since the algorithm does reduction in the r value, if a != r, copy
 	 * the contents of a into r so we can do reduction in r. 
 	 */
 	if (a != r)
 		{
 		if (!bn_wexpand(r, a->top)) return 0;
 		for (j = 0; j < a->top; j++)
 			{
 			r->d[j] = a->d[j];
 			}
 		r->top = a->top;
 		}
 	z = r->d;
 
 	/* start reduction */
 	dN = p[0] / BN_BITS2;  
 	for (j = r->top - 1; j > dN;)
 		{
 		zz = z[j];
 		if (z[j] == 0) { j--; continue; }
 		z[j] = 0;
 
 		for (k = 1; p[k] != 0; k++)
 			{
 			/* reducing component t^p[k] */
 			n = p[0] - p[k];
 			d0 = n % BN_BITS2;  d1 = BN_BITS2 - d0;
 			n /= BN_BITS2; 
 			z[j-n] ^= (zz>>d0);
 			if (d0) z[j-n-1] ^= (zz<> d0);
 		if (d0) z[j-n-1] ^= (zz << d1);
 		}
 
 	/* final round of reduction */
 	while (j == dN)
 		{
 
 		d0 = p[0] % BN_BITS2;
 		zz = z[dN] >> d0;
 		if (zz == 0) break;
 		d1 = BN_BITS2 - d0;
 		
 		/* clear up the top d1 bits */
 		if (d0)
 			z[dN] = (z[dN] << d1) >> d1;
 		else
 			z[dN] = 0;
 		z[0] ^= zz; /* reduction t^0 component */
 
 		for (k = 1; p[k] != 0; k++)
 			{
 			BN_ULONG tmp_ulong;
 
 			/* reducing component t^p[k]*/
 			n = p[k] / BN_BITS2;   
 			d0 = p[k] % BN_BITS2;
 			d1 = BN_BITS2 - d0;
 			z[n] ^= (zz << d0);
 			tmp_ulong = zz >> d1;
                         if (d0 && tmp_ulong)
                                 z[n+1] ^= tmp_ulong;
 			}
 
 		
 		}
 
 	bn_correct_top(r);
 	return 1;
 	}
 
 /* Performs modular reduction of a by p and store result in r.  r could be a.
  *
  * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_arr function.
  */
 int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
 	{
 	int ret = 0;
 	int arr[6];
 	bn_check_top(a);
 	bn_check_top(p);
 	ret = BN_GF2m_poly2arr(p, arr, sizeof(arr)/sizeof(arr[0]));
 	if (!ret || ret > (int)(sizeof(arr)/sizeof(arr[0])))
 		{
 		BNerr(BN_F_BN_GF2M_MOD,BN_R_INVALID_LENGTH);
 		return 0;
 		}
 	ret = BN_GF2m_mod_arr(r, a, arr);
 	bn_check_top(r);
 	return ret;
 	}
 
 
 /* Compute the product of two polynomials a and b, reduce modulo p, and store
  * the result in r.  r could be a or b; a could be b.
  */
 int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
 	{
 	int zlen, i, j, k, ret = 0;
 	BIGNUM *s;
 	BN_ULONG x1, x0, y1, y0, zz[4];
 
 	bn_check_top(a);
 	bn_check_top(b);
 
 	if (a == b)
 		{
 		return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
 		}
 
 	BN_CTX_start(ctx);
 	if ((s = BN_CTX_get(ctx)) == NULL) goto err;
 	
 	zlen = a->top + b->top + 4;
 	if (!bn_wexpand(s, zlen)) goto err;
 	s->top = zlen;
 
 	for (i = 0; i < zlen; i++) s->d[i] = 0;
 
 	for (j = 0; j < b->top; j += 2)
 		{
 		y0 = b->d[j];
 		y1 = ((j+1) == b->top) ? 0 : b->d[j+1];
 		for (i = 0; i < a->top; i += 2)
 			{
 			x0 = a->d[i];
 			x1 = ((i+1) == a->top) ? 0 : a->d[i+1];
 			bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
 			for (k = 0; k < 4; k++) s->d[i+j+k] ^= zz[k];
 			}
 		}
 
 	bn_correct_top(s);
 	if (BN_GF2m_mod_arr(r, s, p))
 		ret = 1;
 	bn_check_top(r);
 
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 /* Compute the product of two polynomials a and b, reduce modulo p, and store
  * the result in r.  r could be a or b; a could equal b.
  *
  * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_mul_arr function.
  */
 int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
 	{
 	int ret = 0;
 	const int max = BN_num_bits(p) + 1;
 	int *arr=NULL;
 	bn_check_top(a);
 	bn_check_top(b);
 	bn_check_top(p);
 	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
 	ret = BN_GF2m_poly2arr(p, arr, max);
 	if (!ret || ret > max)
 		{
 		BNerr(BN_F_BN_GF2M_MOD_MUL,BN_R_INVALID_LENGTH);
 		goto err;
 		}
 	ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
 	bn_check_top(r);
 err:
 	if (arr) OPENSSL_free(arr);
 	return ret;
 	}
 
 
 /* Square a, reduce the result mod p, and store it in a.  r could be a. */
 int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
 	{
 	int i, ret = 0;
 	BIGNUM *s;
 
 	bn_check_top(a);
 	BN_CTX_start(ctx);
 	if ((s = BN_CTX_get(ctx)) == NULL) return 0;
 	if (!bn_wexpand(s, 2 * a->top)) goto err;
 
 	for (i = a->top - 1; i >= 0; i--)
 		{
 		s->d[2*i+1] = SQR1(a->d[i]);
 		s->d[2*i  ] = SQR0(a->d[i]);
 		}
 
 	s->top = 2 * a->top;
 	bn_correct_top(s);
 	if (!BN_GF2m_mod_arr(r, s, p)) goto err;
 	bn_check_top(r);
 	ret = 1;
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 /* Square a, reduce the result mod p, and store it in a.  r could be a.
  *
  * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_sqr_arr function.
  */
 int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 	{
 	int ret = 0;
 	const int max = BN_num_bits(p) + 1;
 	int *arr=NULL;
 
 	bn_check_top(a);
 	bn_check_top(p);
 	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
 	ret = BN_GF2m_poly2arr(p, arr, max);
 	if (!ret || ret > max)
 		{
 		BNerr(BN_F_BN_GF2M_MOD_SQR,BN_R_INVALID_LENGTH);
 		goto err;
 		}
 	ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
 	bn_check_top(r);
 err:
 	if (arr) OPENSSL_free(arr);
 	return ret;
 	}
 
 
 /* Invert a, reduce modulo p, and store the result in r. r could be a. 
  * Uses Modified Almost Inverse Algorithm (Algorithm 10) from
  *     Hankerson, D., Hernandez, J.L., and Menezes, A.  "Software Implementation
  *     of Elliptic Curve Cryptography Over Binary Fields".
  */
 int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 	{
 	BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp;
 	int ret = 0;
 
 	bn_check_top(a);
 	bn_check_top(p);
 
 	BN_CTX_start(ctx);
 	
 	if ((b = BN_CTX_get(ctx))==NULL) goto err;
 	if ((c = BN_CTX_get(ctx))==NULL) goto err;
 	if ((u = BN_CTX_get(ctx))==NULL) goto err;
 	if ((v = BN_CTX_get(ctx))==NULL) goto err;
 
 	if (!BN_GF2m_mod(u, a, p)) goto err;
 	if (BN_is_zero(u)) goto err;
 
 	if (!BN_copy(v, p)) goto err;
 #if 0
 	if (!BN_one(b)) goto err;
 
 	while (1)
 		{
 		while (!BN_is_odd(u))
 			{
 			if (BN_is_zero(u)) goto err;
 			if (!BN_rshift1(u, u)) goto err;
 			if (BN_is_odd(b))
 				{
 				if (!BN_GF2m_add(b, b, p)) goto err;
 				}
 			if (!BN_rshift1(b, b)) goto err;
 			}
 
 		if (BN_abs_is_word(u, 1)) break;
 
 		if (BN_num_bits(u) < BN_num_bits(v))
 			{
 			tmp = u; u = v; v = tmp;
 			tmp = b; b = c; c = tmp;
 			}
 		
 		if (!BN_GF2m_add(u, u, v)) goto err;
 		if (!BN_GF2m_add(b, b, c)) goto err;
 		}
 #else
 	{
-	int i,	ubits = BN_num_bits(u),
-		vbits = BN_num_bits(v),	/* v is copy of p */
-		top = p->top;
-	BN_ULONG *udp,*bdp,*vdp,*cdp;
+        int i;
+        int ubits = BN_num_bits(u);
+        int vbits = BN_num_bits(v); /* v is copy of p */
+        int top = p->top;
+        BN_ULONG *udp, *bdp, *vdp, *cdp;
 
 	bn_wexpand(u,top);	udp = u->d;
 				for (i=u->top;itop = top;
 	bn_wexpand(b,top);	bdp = b->d;
 				bdp[0] = 1;
 				for (i=1;itop = top;
 	bn_wexpand(c,top);	cdp = c->d;
 				for (i=0;itop = top;
 	vdp = v->d;	/* It pays off to "cache" *->d pointers, because
 			 * it allows optimizer to be more aggressive.
 			 * But we don't have to "cache" p->d, because *p
 			 * is declared 'const'... */
 	while (1)
 		{
 		while (ubits && !(udp[0]&1))
 			{
 			BN_ULONG u0,u1,b0,b1,mask;
 
 			u0   = udp[0];
 			b0   = bdp[0];
 			mask = (BN_ULONG)0-(b0&1);
 			b0  ^= p->d[0]&mask;
 			for (i=0;i>1)|(u1<<(BN_BITS2-1)))&BN_MASK2;
 				u0 = u1;
 				b1 = bdp[i+1]^(p->d[i+1]&mask);
 				bdp[i] = ((b0>>1)|(b1<<(BN_BITS2-1)))&BN_MASK2;
 				b0 = b1;
 				}
 			udp[i] = u0>>1;
 			bdp[i] = b0>>1;
 			ubits--;
 			}
 
-		if (ubits<=BN_BITS2 && udp[0]==1) break;
+            if (ubits <= BN_BITS2) {
+                if (udp[0] == 0) /* poly was reducible */
+                    goto err;
+                if (udp[0] == 1)
+                    break;
+            }
 
 		if (ubitsd;
 			bdp = cdp; cdp = c->d;
 			}
 		for(i=0;i 0)
 			{
 			if (!BN_GF2m_add(b, b, a)) goto err;
 			if (!BN_GF2m_add(v, v, u)) goto err;
 			do
 				{
 				if (!BN_rshift1(b, b)) goto err;
 				if (BN_is_odd(v)) if (!BN_GF2m_add(v, v, p)) goto err;
 				if (!BN_rshift1(v, v)) goto err;
 				} while (!BN_is_odd(b));
 			}
 		else if (BN_abs_is_word(a, 1))
 			break;
 		else
 			{
 			if (!BN_GF2m_add(a, a, b)) goto err;
 			if (!BN_GF2m_add(u, u, v)) goto err;
 			do
 				{
 				if (!BN_rshift1(a, a)) goto err;
 				if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
 				if (!BN_rshift1(u, u)) goto err;
 				} while (!BN_is_odd(a));
 			}
 		} while (1);
 
 	if (!BN_copy(r, u)) goto err;
 	bn_check_top(r);
 	ret = 1;
 
 err:
   	BN_CTX_end(ctx);
 	return ret;
 	}
 #endif
 
 /* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx 
  * or yy, xx could equal yy.
  *
  * This function calls down to the BN_GF2m_mod_div implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_div function.
  */
 int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const int p[], BN_CTX *ctx)
 	{
 	BIGNUM *field;
 	int ret = 0;
 
 	bn_check_top(yy);
 	bn_check_top(xx);
 
 	BN_CTX_start(ctx);
 	if ((field = BN_CTX_get(ctx)) == NULL) goto err;
 	if (!BN_GF2m_arr2poly(p, field)) goto err;
 	
 	ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
 	bn_check_top(r);
 
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 
 /* Compute the bth power of a, reduce modulo p, and store
  * the result in r.  r could be a.
  * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363.
  */
 int	BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
 	{
 	int ret = 0, i, n;
 	BIGNUM *u;
 
 	bn_check_top(a);
 	bn_check_top(b);
 
 	if (BN_is_zero(b))
 		return(BN_one(r));
 
 	if (BN_abs_is_word(b, 1))
 		return (BN_copy(r, a) != NULL);
 
 	BN_CTX_start(ctx);
 	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
 	
 	if (!BN_GF2m_mod_arr(u, a, p)) goto err;
 	
 	n = BN_num_bits(b) - 1;
 	for (i = n - 1; i >= 0; i--)
 		{
 		if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) goto err;
 		if (BN_is_bit_set(b, i))
 			{
 			if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) goto err;
 			}
 		}
 	if (!BN_copy(r, u)) goto err;
 	bn_check_top(r);
 	ret = 1;
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 /* Compute the bth power of a, reduce modulo p, and store
  * the result in r.  r could be a.
  *
  * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_exp_arr function.
  */
 int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
 	{
 	int ret = 0;
 	const int max = BN_num_bits(p) + 1;
 	int *arr=NULL;
 	bn_check_top(a);
 	bn_check_top(b);
 	bn_check_top(p);
 	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
 	ret = BN_GF2m_poly2arr(p, arr, max);
 	if (!ret || ret > max)
 		{
 		BNerr(BN_F_BN_GF2M_MOD_EXP,BN_R_INVALID_LENGTH);
 		goto err;
 		}
 	ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
 	bn_check_top(r);
 err:
 	if (arr) OPENSSL_free(arr);
 	return ret;
 	}
 
 /* Compute the square root of a, reduce modulo p, and store
  * the result in r.  r could be a.
  * Uses exponentiation as in algorithm A.4.1 from IEEE P1363.
  */
 int	BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *u;
 
 	bn_check_top(a);
 
 	if (!p[0])
 		{
 		/* reduction mod 1 => return 0 */
 		BN_zero(r);
 		return 1;
 		}
 
 	BN_CTX_start(ctx);
 	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
 	
 	if (!BN_set_bit(u, p[0] - 1)) goto err;
 	ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
 	bn_check_top(r);
 
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 /* Compute the square root of a, reduce modulo p, and store
  * the result in r.  r could be a.
  *
  * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_sqrt_arr function.
  */
 int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 	{
 	int ret = 0;
 	const int max = BN_num_bits(p) + 1;
 	int *arr=NULL;
 	bn_check_top(a);
 	bn_check_top(p);
 	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
 	ret = BN_GF2m_poly2arr(p, arr, max);
 	if (!ret || ret > max)
 		{
 		BNerr(BN_F_BN_GF2M_MOD_SQRT,BN_R_INVALID_LENGTH);
 		goto err;
 		}
 	ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
 	bn_check_top(r);
 err:
 	if (arr) OPENSSL_free(arr);
 	return ret;
 	}
 
 /* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
  * Uses algorithms A.4.7 and A.4.6 from IEEE P1363.
  */
 int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], BN_CTX *ctx)
 	{
 	int ret = 0, count = 0, j;
 	BIGNUM *a, *z, *rho, *w, *w2, *tmp;
 
 	bn_check_top(a_);
 
 	if (!p[0])
 		{
 		/* reduction mod 1 => return 0 */
 		BN_zero(r);
 		return 1;
 		}
 
 	BN_CTX_start(ctx);
 	a = BN_CTX_get(ctx);
 	z = BN_CTX_get(ctx);
 	w = BN_CTX_get(ctx);
 	if (w == NULL) goto err;
 
 	if (!BN_GF2m_mod_arr(a, a_, p)) goto err;
 	
 	if (BN_is_zero(a))
 		{
 		BN_zero(r);
 		ret = 1;
 		goto err;
 		}
 
 	if (p[0] & 0x1) /* m is odd */
 		{
 		/* compute half-trace of a */
 		if (!BN_copy(z, a)) goto err;
 		for (j = 1; j <= (p[0] - 1) / 2; j++)
 			{
 			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
 			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
 			if (!BN_GF2m_add(z, z, a)) goto err;
 			}
 		
 		}
 	else /* m is even */
 		{
 		rho = BN_CTX_get(ctx);
 		w2 = BN_CTX_get(ctx);
 		tmp = BN_CTX_get(ctx);
 		if (tmp == NULL) goto err;
 		do
 			{
 			if (!BN_rand(rho, p[0], 0, 0)) goto err;
 			if (!BN_GF2m_mod_arr(rho, rho, p)) goto err;
 			BN_zero(z);
 			if (!BN_copy(w, rho)) goto err;
 			for (j = 1; j <= p[0] - 1; j++)
 				{
 				if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
 				if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) goto err;
 				if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) goto err;
 				if (!BN_GF2m_add(z, z, tmp)) goto err;
 				if (!BN_GF2m_add(w, w2, rho)) goto err;
 				}
 			count++;
 			} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
 		if (BN_is_zero(w))
 			{
 			BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS);
 			goto err;
 			}
 		}
 	
 	if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err;
 	if (!BN_GF2m_add(w, z, w)) goto err;
 	if (BN_GF2m_cmp(w, a))
 		{
 		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
 		goto err;
 		}
 
 	if (!BN_copy(r, z)) goto err;
 	bn_check_top(r);
 
 	ret = 1;
 
 err:
 	BN_CTX_end(ctx);
 	return ret;
 	}
 
 /* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
  *
  * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper
  * function is only provided for convenience; for best performance, use the 
  * BN_GF2m_mod_solve_quad_arr function.
  */
 int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 	{
 	int ret = 0;
 	const int max = BN_num_bits(p) + 1;
 	int *arr=NULL;
 	bn_check_top(a);
 	bn_check_top(p);
 	if ((arr = (int *)OPENSSL_malloc(sizeof(int) *
 						max)) == NULL) goto err;
 	ret = BN_GF2m_poly2arr(p, arr, max);
 	if (!ret || ret > max)
 		{
 		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH);
 		goto err;
 		}
 	ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
 	bn_check_top(r);
 err:
 	if (arr) OPENSSL_free(arr);
 	return ret;
 	}
 
 /* Convert the bit-string representation of a polynomial
  * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding 
  * to the bits with non-zero coefficient.  Array is terminated with -1.
  * Up to max elements of the array will be filled.  Return value is total
  * number of array elements that would be filled if array was large enough.
  */
 int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
 	{
 	int i, j, k = 0;
 	BN_ULONG mask;
 
 	if (BN_is_zero(a))
 		return 0;
 
 	for (i = a->top - 1; i >= 0; i--)
 		{
 		if (!a->d[i])
 			/* skip word if a->d[i] == 0 */
 			continue;
 		mask = BN_TBIT;
 		for (j = BN_BITS2 - 1; j >= 0; j--)
 			{
 			if (a->d[i] & mask) 
 				{
 				if (k < max) p[k] = BN_BITS2 * i + j;
 				k++;
 				}
 			mask >>= 1;
 			}
 		}
 
 	if (k < max) {
 		p[k] = -1;
 		k++;
 	}
 
 	return k;
 	}
 
 /* Convert the coefficient array representation of a polynomial to a 
  * bit-string.  The array must be terminated by -1.
  */
 int BN_GF2m_arr2poly(const int p[], BIGNUM *a)
 	{
 	int i;
 
 	bn_check_top(a);
 	BN_zero(a);
 	for (i = 0; p[i] != -1; i++)
 		{
 		if (BN_set_bit(a, p[i]) == 0)
 			return 0;
 		}
 	bn_check_top(a);
 
 	return 1;
 	}
 
 #endif
Index: releng/10.1/crypto/openssl/crypto/bn/bn_print.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/bn/bn_print.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/bn/bn_print.c	(revision 284295)
@@ -1,378 +1,383 @@
 /* crypto/bn/bn_print.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include "bn_lcl.h"
 
 static const char Hex[]="0123456789ABCDEF";
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2hex(const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	char *buf;
 	char *p;
 
-	buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2);
+	if (a->neg && BN_is_zero(a)) {
+	    /* "-0" == 3 bytes including NULL terminator */
+	    buf = OPENSSL_malloc(3);
+	} else {
+	    buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
+	}
 	if (buf == NULL)
 		{
 		BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	p=buf;
 	if (a->neg) *(p++)='-';
 	if (BN_is_zero(a)) *(p++)='0';
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-8; j >= 0; j-=8)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0xff;
 			if (z || (v != 0))
 				{
 				*(p++)=Hex[v>>4];
 				*(p++)=Hex[v&0x0f];
 				z=1;
 				}
 			}
 		}
 	*p='\0';
 err:
 	return(buf);
 	}
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2dec(const BIGNUM *a)
 	{
 	int i=0,num, ok = 0;
 	char *buf=NULL;
 	char *p;
 	BIGNUM *t=NULL;
 	BN_ULONG *bn_data=NULL,*lp;
 
 	/* get an upper bound for the length of the decimal integer
 	 * num <= (BN_num_bits(a) + 1) * log(2)
 	 *     <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1     (rounding error)
 	 *     <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 
 	 */
 	i=BN_num_bits(a)*3;
 	num=(i/10+i/1000+1)+1;
 	bn_data=(BN_ULONG *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
 	buf=(char *)OPENSSL_malloc(num+3);
 	if ((buf == NULL) || (bn_data == NULL))
 		{
 		BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	if ((t=BN_dup(a)) == NULL) goto err;
 
 #define BUF_REMAIN (num+3 - (size_t)(p - buf))
 	p=buf;
 	lp=bn_data;
 	if (BN_is_zero(t))
 		{
 		*(p++)='0';
 		*(p++)='\0';
 		}
 	else
 		{
 		if (BN_is_negative(t))
 			*p++ = '-';
 
 		i=0;
 		while (!BN_is_zero(t))
 			{
 			*lp=BN_div_word(t,BN_DEC_CONV);
 			lp++;
 			}
 		lp--;
 		/* We now have a series of blocks, BN_DEC_NUM chars
 		 * in length, where the last one needs truncation.
 		 * The blocks need to be reversed in order. */
 		BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT1,*lp);
 		while (*p) p++;
 		while (lp != bn_data)
 			{
 			lp--;
 			BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT2,*lp);
 			while (*p) p++;
 			}
 		}
 	ok = 1;
 err:
 	if (bn_data != NULL) OPENSSL_free(bn_data);
 	if (t != NULL) BN_free(t);
 	if (!ok && buf)
 		{
 		OPENSSL_free(buf);
 		buf = NULL;
 		}
 
 	return(buf);
 	}
 
 int BN_hex2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,h,m,i,j,k,c;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isxdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the hex digits, and it is 'i' long */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of hex digests; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=i; /* least significant 'hex' */
 	m=0;
 	h=0;
 	while (j > 0)
 		{
 		m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
 		l=0;
 		for (;;)
 			{
 			c=a[j-m];
 			if ((c >= '0') && (c <= '9')) k=c-'0';
 			else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
 			else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
 			else k=0; /* paranoia */
 			l=(l<<4)|k;
 
 			if (--m <= 0)
 				{
 				ret->d[h++]=l;
 				break;
 				}
 			}
 		j-=(BN_BYTES*2);
 		}
 	ret->top=h;
 	bn_correct_top(ret);
 	ret->neg=neg;
 
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 int BN_dec2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,i,j;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the digits, and it is 'i' long.
 	 * We chop it into BN_DEC_NUM digits at a time */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of digests, a bit of an over expand; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=BN_DEC_NUM-(i%BN_DEC_NUM);
 	if (j == BN_DEC_NUM) j=0;
 	l=0;
 	while (*a)
 		{
 		l*=10;
 		l+= *a-'0';
 		a++;
 		if (++j == BN_DEC_NUM)
 			{
 			BN_mul_word(ret,BN_DEC_CONV);
 			BN_add_word(ret,l);
 			l=0;
 			j=0;
 			}
 		}
 	ret->neg=neg;
 
 	bn_correct_top(ret);
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 int BN_asc2bn(BIGNUM **bn, const char *a)
 	{
 	const char *p = a;
 	if (*p == '-')
 		p++;
 
 	if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x'))
 		{		
 		if (!BN_hex2bn(bn, p + 2))
 			return 0;
 		}
 	else
 		{
 		if (!BN_dec2bn(bn, p))
 			return 0;
 		}
 	if (*a == '-')
 		(*bn)->neg = 1;
 	return 1;
 	}
 
 #ifndef OPENSSL_NO_BIO
 #ifndef OPENSSL_NO_FP_API
 int BN_print_fp(FILE *fp, const BIGNUM *a)
 	{
 	BIO *b;
 	int ret;
 
 	if ((b=BIO_new(BIO_s_file())) == NULL)
 		return(0);
 	BIO_set_fp(b,fp,BIO_NOCLOSE);
 	ret=BN_print(b,a);
 	BIO_free(b);
 	return(ret);
 	}
 #endif
 
 int BN_print(BIO *bp, const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	int ret=0;
 
 	if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
 	if (BN_is_zero(a) && (BIO_write(bp,"0",1) != 1)) goto end;
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-4; j >= 0; j-=4)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0x0f;
 			if (z || (v != 0))
 				{
 				if (BIO_write(bp,&(Hex[v]),1) != 1)
 					goto end;
 				z=1;
 				}
 			}
 		}
 	ret=1;
 end:
 	return(ret);
 	}
 #endif
 
 char *BN_options(void)
 	{
 	static int init=0;
 	static char data[16];
 
 	if (!init)
 		{
 		init++;
 #ifdef BN_LLONG
 		BIO_snprintf(data,sizeof data,"bn(%d,%d)",
 			     (int)sizeof(BN_ULLONG)*8,(int)sizeof(BN_ULONG)*8);
 #else
 		BIO_snprintf(data,sizeof data,"bn(%d,%d)",
 			     (int)sizeof(BN_ULONG)*8,(int)sizeof(BN_ULONG)*8);
 #endif
 		}
 	return(data);
 	}
Index: releng/10.1/crypto/openssl/crypto/buffer/buffer.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/buffer/buffer.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/buffer/buffer.c	(revision 284295)
@@ -1,203 +1,203 @@
 /* crypto/buffer/buffer.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include "cryptlib.h"
 #include 
 
 /* LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That
  * function is applied in several functions in this file and this limit ensures
  * that the result fits in an int. */
 #define LIMIT_BEFORE_EXPANSION 0x5ffffffc
 
 BUF_MEM *BUF_MEM_new(void)
 	{
 	BUF_MEM *ret;
 
 	ret=OPENSSL_malloc(sizeof(BUF_MEM));
 	if (ret == NULL)
 		{
 		BUFerr(BUF_F_BUF_MEM_NEW,ERR_R_MALLOC_FAILURE);
 		return(NULL);
 		}
 	ret->length=0;
 	ret->max=0;
 	ret->data=NULL;
 	return(ret);
 	}
 
 void BUF_MEM_free(BUF_MEM *a)
 	{
 	if(a == NULL)
 	    return;
 
 	if (a->data != NULL)
 		{
-		memset(a->data,0,(unsigned int)a->max);
+		OPENSSL_cleanse(a->data, a->max);
 		OPENSSL_free(a->data);
 		}
 	OPENSSL_free(a);
 	}
 
 int BUF_MEM_grow(BUF_MEM *str, size_t len)
 	{
 	char *ret;
 	size_t n;
 
 	if (str->length >= len)
 		{
 		str->length=len;
 		return(len);
 		}
 	if (str->max >= len)
 		{
 		memset(&str->data[str->length],0,len-str->length);
 		str->length=len;
 		return(len);
 		}
 	/* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
 	if (len > LIMIT_BEFORE_EXPANSION)
 		{
 		BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	n=(len+3)/3*4;
 	if (str->data == NULL)
 		ret=OPENSSL_malloc(n);
 	else
 		ret=OPENSSL_realloc(str->data,n);
 	if (ret == NULL)
 		{
 		BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE);
 		len=0;
 		}
 	else
 		{
 		str->data=ret;
 		str->max=n;
 		memset(&str->data[str->length],0,len-str->length);
 		str->length=len;
 		}
 	return(len);
 	}
 
 int BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
 	{
 	char *ret;
 	size_t n;
 
 	if (str->length >= len)
 		{
 		memset(&str->data[len],0,str->length-len);
 		str->length=len;
 		return(len);
 		}
 	if (str->max >= len)
 		{
 		memset(&str->data[str->length],0,len-str->length);
 		str->length=len;
 		return(len);
 		}
 	/* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
 	if (len > LIMIT_BEFORE_EXPANSION)
 		{
 		BUFerr(BUF_F_BUF_MEM_GROW_CLEAN,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	n=(len+3)/3*4;
 	if (str->data == NULL)
 		ret=OPENSSL_malloc(n);
 	else
 		ret=OPENSSL_realloc_clean(str->data,str->max,n);
 	if (ret == NULL)
 		{
 		BUFerr(BUF_F_BUF_MEM_GROW_CLEAN,ERR_R_MALLOC_FAILURE);
 		len=0;
 		}
 	else
 		{
 		str->data=ret;
 		str->max=n;
 		memset(&str->data[str->length],0,len-str->length);
 		str->length=len;
 		}
 	return(len);
 	}
 
 void BUF_reverse(unsigned char *out, const unsigned char *in, size_t size)
 	{
 	size_t i;
 	if (in)
 		{
 		out += size - 1;
 		for (i = 0; i < size; i++)
 			*out-- = *in++;
 		}
 	else
 		{
 		unsigned char *q;
 		char c;
 		q = out + size - 1;
 		for (i = 0; i < size/2; i++)
 			{
 			c = *q;
 			*q-- = *out;
 			*out++ = c;
 			}
 		}
 	}
Index: releng/10.1/crypto/openssl/crypto/cms/cms_smime.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/cms/cms_smime.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/cms/cms_smime.c	(revision 284295)
@@ -1,851 +1,851 @@
 /* crypto/cms/cms_smime.c */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  */
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include "cms_lcl.h"
 
 static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
 	{
 	unsigned char buf[4096];
 	int r = 0, i;
 	BIO *tmpout = NULL;
 
 	if (out == NULL)
 		tmpout = BIO_new(BIO_s_null());
 	else if (flags & CMS_TEXT)
 		{
 		tmpout = BIO_new(BIO_s_mem());
 		BIO_set_mem_eof_return(tmpout, 0);
 		}
 	else
 		tmpout = out;
 
 	if(!tmpout)
 		{
 		CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* Read all content through chain to process digest, decrypt etc */
 	for (;;)
 	{
 		i=BIO_read(in,buf,sizeof(buf));
 		if (i <= 0)
 			{
 			if (BIO_method_type(in) == BIO_TYPE_CIPHER)
 				{
 				if (!BIO_get_cipher_status(in))
 					goto err;
 				}
 			if (i < 0)
 				goto err;
 			break;
 			}
 				
 		if (tmpout && (BIO_write(tmpout, buf, i) != i))
 			goto err;
 	}
 
 	if(flags & CMS_TEXT)
 		{
 		if(!SMIME_text(tmpout, out))
 			{
 			CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
 			goto err;
 			}
 		}
 
 	r = 1;
 
 	err:
 	if (tmpout && (tmpout != out))
 		BIO_free(tmpout);
 	return r;
 
 	}
 
 static int check_content(CMS_ContentInfo *cms)
 	{
 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
 	if (!pos || !*pos)
 		{
 		CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
 		return 0;
 		}
 	return 1;
 	}
 
 static void do_free_upto(BIO *f, BIO *upto)
 	{
 	if (upto)
 		{
 		BIO *tbio;
 		do 
 			{
 			tbio = BIO_pop(f);
 			BIO_free(f);
 			f = tbio;
 			}
-		while (f != upto);
+		while (f && f != upto);
 		}
 	else
 		BIO_free_all(f);
 	}
 
 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data)
 		{
 		CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
 		return 0;
 		}
 	cont = CMS_dataInit(cms, NULL);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	BIO_free_all(cont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	cms = cms_Data_create();
 	if (!cms)
 		return NULL;
 
 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 
 	return NULL;
 	}
 
 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest)
 		{
 		CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	if (r)
 		r = cms_DigestedData_do_final(cms, cont, 1);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!md)
 		md = EVP_sha1();
 	cms = cms_DigestedData_create(md);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		CMS_set_detached(cms, 0);
 
 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
 				const unsigned char *key, size_t keylen,
 				BIO *dcont, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
 					CMS_R_TYPE_NOT_ENCRYPTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
 					const unsigned char *key, size_t keylen,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!cipher)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
 		return NULL;
 		}
 	cms = CMS_ContentInfo_new();
 	if (!cms)
 		return NULL;
 	if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		CMS_set_detached(cms, 0);
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
 					X509_STORE *store,
 					STACK_OF(X509) *certs,
 					STACK_OF(X509_CRL) *crls,
 					unsigned int flags)
 	{
 	X509_STORE_CTX ctx;
 	X509 *signer;
 	int i, j, r = 0;
 	CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 	if (!X509_STORE_CTX_init(&ctx, store, signer, certs))
 		{
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_STORE_INIT_ERROR);
 		goto err;
 		}
 	X509_STORE_CTX_set_default(&ctx, "smime_sign");
 	if (crls)
 		X509_STORE_CTX_set0_crls(&ctx, crls);
 
 	i = X509_verify_cert(&ctx);
 	if (i <= 0)
 		{
 		j = X509_STORE_CTX_get_error(&ctx);
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_CERTIFICATE_VERIFY_ERROR);
 		ERR_add_error_data(2, "Verify error:",
 					 X509_verify_cert_error_string(j));
 		goto err;
 		}
 	r = 1;
 	err:
 	X509_STORE_CTX_cleanup(&ctx);
 	return r;
 
 	}
 
 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 		 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
 	{
 	CMS_SignerInfo *si;
 	STACK_OF(CMS_SignerInfo) *sinfos;
 	STACK_OF(X509) *cms_certs = NULL;
 	STACK_OF(X509_CRL) *crls = NULL;
 	X509 *signer;
 	int i, scount = 0, ret = 0;
 	BIO *cmsbio = NULL, *tmpin = NULL;
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	/* Attempt to find all signer certificates */
 
 	sinfos = CMS_get0_SignerInfos(cms);
 
 	if (sk_CMS_SignerInfo_num(sinfos) <= 0)
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
 		goto err;
 		}
 
 	for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 		{
 		si = sk_CMS_SignerInfo_value(sinfos, i);
 		CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 		if (signer)
 			scount++;
 		}
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		scount += CMS_set1_signers_certs(cms, certs, flags);
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
 		goto err;
 		}
 
 	/* Attempt to verify all signers certs */
 
 	if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
 		{
 		cms_certs = CMS_get1_certs(cms);
 		if (!(flags & CMS_NOCRL))
 			crls = CMS_get1_crls(cms);
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (!cms_signerinfo_verify_cert(si, store,
 							cms_certs, crls, flags))
 				goto err;
 			}
 		}
 
 	/* Attempt to verify all SignerInfo signed attribute signatures */
 
 	if (!(flags & CMS_NO_ATTR_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_signed_get_attr_count(si) < 0)
 				continue;
 			if (CMS_SignerInfo_verify(si) <= 0)
 				goto err;
 			}
 		}
 
 	/* Performance optimization: if the content is a memory BIO then
 	 * store its contents in a temporary read only memory BIO. This
 	 * avoids potentially large numbers of slow copies of data which will
 	 * occur when reading from a read write memory BIO when signatures
 	 * are calculated.
 	 */
 
 	if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM))
 		{
 		char *ptr;
 		long len;
 		len = BIO_get_mem_data(dcont, &ptr);
 		tmpin = BIO_new_mem_buf(ptr, len);
 		if (tmpin == NULL)
 			{
 			CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		}
 	else
 		tmpin = dcont;
 		
 
 	cmsbio=CMS_dataInit(cms, tmpin);
 	if (!cmsbio)
 		goto err;
 
 	if (!cms_copy_content(out, cmsbio, flags))
 		goto err;
 
 	if (!(flags & CMS_NO_CONTENT_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)
 				{
 				CMSerr(CMS_F_CMS_VERIFY,
 					CMS_R_CONTENT_VERIFY_ERROR);
 				goto err;
 				}
 			}
 		}
 
 	ret = 1;
 
 	err:
 	
 	if (dcont && (tmpin == dcont))
 		do_free_upto(cmsbio, dcont);
 	else
 		BIO_free_all(cmsbio);
 
 	if (cms_certs)
 		sk_X509_pop_free(cms_certs, X509_free);
 	if (crls)
 		sk_X509_CRL_pop_free(crls, X509_CRL_free);
 
 	return ret;
 	}
 
 int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
 			STACK_OF(X509) *certs,
 			X509_STORE *store, unsigned int flags)
 	{
 	int r;
 	flags &= ~(CMS_DETACHED|CMS_TEXT);
 	r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
 	if (r <= 0)
 		return r;
 	return cms_Receipt_verify(rcms, ocms);
 	}
 
 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
 						BIO *data, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 
 	cms = CMS_ContentInfo_new();
 	if (!cms || !CMS_SignedData_init(cms))
 		goto merr;
 
 	if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
 		{
 		CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		X509 *x = sk_X509_value(certs, i);
 		if (!CMS_add1_cert(cms, x))
 			goto merr;
 		}
 
 	if(!(flags & CMS_DETACHED))
 		CMS_set_detached(cms, 0);
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
 
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 					X509 *signcert, EVP_PKEY *pkey,
 					STACK_OF(X509) *certs,
 					unsigned int flags)
 	{
 	CMS_SignerInfo *rct_si;
 	CMS_ContentInfo *cms = NULL;
 	ASN1_OCTET_STRING **pos, *os;
 	BIO *rct_cont = NULL;
 	int r = 0;
 
 	flags &= ~(CMS_STREAM|CMS_TEXT);
 	/* Not really detached but avoids content being allocated */
 	flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
 	if (!pkey || !signcert)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
 		return NULL;
 		}
 
 	/* Initialize signed data */
 
 	cms = CMS_sign(NULL, NULL, certs, NULL, flags);
 	if (!cms)
 		goto err;
 
 	/* Set inner content type to signed receipt */
 	if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
 		goto err;
 
 	rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
 	if (!rct_si)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	os = cms_encode_Receipt(si);
 
 	if (!os)
 		goto err;
 
 	/* Set content to digest */
 	rct_cont = BIO_new_mem_buf(os->data, os->length);
 	if (!rct_cont)
 		goto err;
 
 	/* Add msgSigDigest attribute */
 
 	if (!cms_msgSigDigest_add1(rct_si, si))
 		goto err;
 
 	/* Finalize structure */
 	if (!CMS_final(cms, rct_cont, NULL, flags))
 		goto err;
 
 	/* Set embedded content */
 	pos = CMS_get0_content(cms);
 	*pos = os;
 
 	r = 1;
 
 	err:
 	if (rct_cont)
 		BIO_free(rct_cont);
 	if (r)
 		return cms;
 	CMS_ContentInfo_free(cms);
 	return NULL;
 
 	}
 
 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
 				const EVP_CIPHER *cipher, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 	X509 *recip;
 	cms = CMS_EnvelopedData_create(cipher);
 	if (!cms)
 		goto merr;
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		recip = sk_X509_value(certs, i);
 		if (!CMS_add1_recipient_cert(cms, recip, flags))
 			{
 			CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
 			goto err;
 			}
 		}
 
 	if(!(flags & CMS_DETACHED))
 		CMS_set_detached(cms, 0);
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	int debug = 0, ri_match = 0;
 	ris = CMS_get0_RecipientInfos(cms);
 	if (ris)
 		debug = cms->d.envelopedData->encryptedContentInfo->debug;
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
 				continue;
 		ri_match = 1;
 		/* If we have a cert try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
 			{
 			CMS_RecipientInfo_set0_pkey(ri, pk);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_pkey(ri, NULL);
 			if (cert)
 				{
 				/* If not debugging clear any error and
 				 * return success to avoid leaking of
 				 * information useful to MMA
 				 */
 				if (!debug)
 					{
 					ERR_clear_error();
 					return 1;
 					}
 				if (r > 0)
 					return 1;
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			/* If no cert and not debugging don't leave loop
 			 * after first successful decrypt. Always attempt
 			 * to decrypt all recipients to avoid leaking timing
 			 * of a successful decrypt.
 			 */
 			else if (r > 0 && debug)
 				return 1;
 			}
 		}
 	/* If no cert and not debugging always return success */
 	if (ri_match && !cert && !debug)
 		{
 		ERR_clear_error();
 		return 1;
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 
 int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
 				unsigned char *key, size_t keylen,
 				unsigned char *id, size_t idlen)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	ris = CMS_get0_RecipientInfos(cms);
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
 				continue;
 
 		/* If we have an id try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
 			{
 			CMS_RecipientInfo_set0_key(ri, key, keylen);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_key(ri, NULL, 0);
 			if (r > 0)
 				return 1;
 			if (id)
 				{
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			ERR_clear_error();
 			}
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 
 int CMS_decrypt_set1_password(CMS_ContentInfo *cms, 
 				unsigned char *pass, ossl_ssize_t passlen)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	ris = CMS_get0_RecipientInfos(cms);
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
 				continue;
 		CMS_RecipientInfo_set0_password(ri, pass, passlen);
 		r = CMS_RecipientInfo_decrypt(cms, ri);
 		CMS_RecipientInfo_set0_password(ri, NULL, 0);
 		if (r > 0)
 			return 1;
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 	
 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
 				BIO *dcont, BIO *out,
 				unsigned int flags)
 	{
 	int r;
 	BIO *cont;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
 		{
 		CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
 		return 0;
 		}
 	if (!dcont && !check_content(cms))
 		return 0;
 	if (flags & CMS_DEBUG_DECRYPT)
 		cms->d.envelopedData->encryptedContentInfo->debug = 1;
 	else
 		cms->d.envelopedData->encryptedContentInfo->debug = 0;
 	if (!pk && !cert && !dcont && !out)
 		return 1;
 	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
 	{
 	BIO *cmsbio;
 	int ret = 0;
 	if (!(cmsbio = CMS_dataInit(cms, dcont)))
 		{
 		CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	SMIME_crlf_copy(data, cmsbio, flags);
 
 	(void)BIO_flush(cmsbio);
 
 
         if (!CMS_dataFinal(cms, cmsbio))
 		{
 		CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR);
 		goto err;
 		}
 
 	ret = 1;
 
 	err:
 	do_free_upto(cmsbio, dcont);
 
 	return ret;
 
 	}
 
 #ifdef ZLIB
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData)
 		{
 		CMSerr(CMS_F_CMS_UNCOMPRESS,
 					CMS_R_TYPE_NOT_COMPRESSED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (comp_nid <= 0)
 		comp_nid = NID_zlib_compression;
 	cms = cms_CompressedData_create(comp_nid);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		CMS_set_detached(cms, 0);
 
 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 #else
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return 0;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return NULL;
 	}
 
 #endif
Index: releng/10.1/crypto/openssl/crypto/ec/ec2_oct.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ec2_oct.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ec2_oct.c	(revision 284295)
@@ -1,407 +1,408 @@
 /* crypto/ec/ec2_oct.c */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
  * to the OpenSSL project.
  *
  * The ECC Code is licensed pursuant to the OpenSSL open source
  * license provided below.
  *
  * The software is originally written by Sheueling Chang Shantz and
  * Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 
 #include "ec_lcl.h"
 
 #ifndef OPENSSL_NO_EC2M
 
 /* Calculates and sets the affine coordinates of an EC_POINT from the given
  * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1. 
  * Note that the simple implementation only uses affine coordinates.
  *
  * The method is from the following publication:
  * 
  *     Harper, Menezes, Vanstone:
  *     "Public-Key Cryptosystems with Very Small Key Lengths",
  *     EUROCRYPT '92, Springer-Verlag LNCS 658,
  *     published February 1993
  *
  * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
  * the same method, but claim no priority date earlier than July 29, 1994
  * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
  */
 int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp, *x, *y, *z;
 	int ret = 0, z0;
 
 	/* clear error queue */
 	ERR_clear_error();
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	y_bit = (y_bit != 0) ? 1 : 0;
 
 	BN_CTX_start(ctx);
 	tmp = BN_CTX_get(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	z = BN_CTX_get(ctx);
 	if (z == NULL) goto err;
 
 	if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
 	if (BN_is_zero(x))
 		{
 		if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
 		}
 	else
 		{
 		if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
 		if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
 		if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
 		if (!BN_GF2m_add(tmp, x, tmp)) goto err;
 		if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
 			{
 			unsigned long err = ERR_peek_last_error();
 			
 			if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
 				{
 				ERR_clear_error();
 				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 				}
 			else
 				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
 			goto err;
 			}
 		z0 = (BN_is_odd(z)) ? 1 : 0;
 		if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
 		if (z0 != y_bit)
 			{
 			if (!BN_GF2m_add(y, y, x)) goto err;
 			}
 		}
 
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Converts an EC_POINT to an octet string.  
  * If buf is NULL, the encoded length will be returned.
  * If the length len of buf is smaller than required an error will be returned.
  */
 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, i, skip;
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		yxi = BN_CTX_get(ctx);
 		if (yxi == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 
 		buf[0] = form;
 		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (BN_is_odd(yxi)) buf[0]++;
 			}
 
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 /* Converts an octet string representation to an EC_POINT. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	yxi = BN_CTX_get(ctx);
 	if (yxi == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (y_bit != BN_is_odd(yxi))
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 #endif
Index: releng/10.1/crypto/openssl/crypto/ec/ec_check.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ec_check.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ec_check.c	(revision 284295)
@@ -1,123 +1,123 @@
 /* crypto/ec/ec_check.c */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include "ec_lcl.h"
 #include 
 
 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *order;
 	BN_CTX *new_ctx = NULL;
 	EC_POINT *point = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	if ((order = BN_CTX_get(ctx)) == NULL) goto err;
 
 	/* check the discriminant */
 	if (!EC_GROUP_check_discriminant(group, ctx))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
 		goto err;
 		}
 
 	/* check the generator */
 	if (group->generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
 		goto err;
 		}
-	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
+	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	/* check the order of the generator */
 	if ((point = EC_POINT_new(group)) == NULL) goto err;
 	if (!EC_GROUP_get_order(group, order, ctx)) goto err; 
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
 		goto err;
 		}
 	
 	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
 	if (!EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	if (point)
 		EC_POINT_free(point);
 	return ret;
 	}
Index: releng/10.1/crypto/openssl/crypto/ec/ec_key.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ec_key.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ec_key.c	(revision 284295)
@@ -1,572 +1,572 @@
 /* crypto/ec/ec_key.c */
 /*
  * Written by Nils Larsch for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions originally developed by SUN MICROSYSTEMS, INC., and 
  * contributed to the OpenSSL project.
  */
 
 #include 
 #include "ec_lcl.h"
 #include 
 #ifdef OPENSSL_FIPS
 #include 
 #endif
 
 EC_KEY *EC_KEY_new(void)
 	{
 	EC_KEY *ret;
 
 	ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE);
 		return(NULL);
 		}
 
 	ret->version = 1;	
 	ret->flags = 0;
 	ret->group   = NULL;
 	ret->pub_key = NULL;
 	ret->priv_key= NULL;
 	ret->enc_flag= 0; 
 	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
 	ret->references= 1;
 	ret->method_data = NULL;
 	return(ret);
 	}
 
 EC_KEY *EC_KEY_new_by_curve_name(int nid)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	ret->group = EC_GROUP_new_by_curve_name(nid);
 	if (ret->group == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 void EC_KEY_free(EC_KEY *r)
 	{
 	int i;
 
 	if (r == NULL) return;
 
 	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"EC_KEY_free, bad reference count\n");
 		abort();
 		}
 #endif
 
 	if (r->group    != NULL) 
 		EC_GROUP_free(r->group);
 	if (r->pub_key  != NULL)
 		EC_POINT_free(r->pub_key);
 	if (r->priv_key != NULL)
 		BN_clear_free(r->priv_key);
 
 	EC_EX_DATA_free_all_data(&r->method_data);
 
 	OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
 
 	OPENSSL_free(r);
 	}
 
 EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest == NULL || src == NULL)
 		{
 		ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	/* copy the parameters */
 	if (src->group)
 		{
 		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
 		/* clear the old group */
 		if (dest->group)
 			EC_GROUP_free(dest->group);
 		dest->group = EC_GROUP_new(meth);
 		if (dest->group == NULL)
 			return NULL;
 		if (!EC_GROUP_copy(dest->group, src->group))
 			return NULL;
 		}
 	/*  copy the public key */
 	if (src->pub_key && src->group)
 		{
 		if (dest->pub_key)
 			EC_POINT_free(dest->pub_key);
 		dest->pub_key = EC_POINT_new(src->group);
 		if (dest->pub_key == NULL)
 			return NULL;
 		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
 			return NULL;
 		}
 	/* copy the private key */
 	if (src->priv_key)
 		{
 		if (dest->priv_key == NULL)
 			{
 			dest->priv_key = BN_new();
 			if (dest->priv_key == NULL)
 				return NULL;
 			}
 		if (!BN_copy(dest->priv_key, src->priv_key))
 			return NULL;
 		}
 	/* copy method/extra data */
 	EC_EX_DATA_free_all_data(&dest->method_data);
 
 	for (d = src->method_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	/* copy the rest */
 	dest->enc_flag  = src->enc_flag;
 	dest->conv_form = src->conv_form;
 	dest->version   = src->version;
 	dest->flags = src->flags;
 
 	return dest;
 	}
 
 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	if (EC_KEY_copy(ret, ec_key) == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 int EC_KEY_up_ref(EC_KEY *r)
 	{
 	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 #ifdef REF_CHECK
 	if (i < 2)
 		{
 		fprintf(stderr, "EC_KEY_up, bad reference count\n");
 		abort();
 		}
 #endif
 	return ((i > 1) ? 1 : 0);
 	}
 
 int EC_KEY_generate_key(EC_KEY *eckey)
 	{	
 	int	ok = 0;
 	BN_CTX	*ctx = NULL;
 	BIGNUM	*priv_key = NULL, *order = NULL;
 	EC_POINT *pub_key = NULL;
 
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode())
 		return FIPS_ec_key_generate_key(eckey);
 #endif
 
 	if (!eckey || !eckey->group)
 		{
 		ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if ((order = BN_new()) == NULL) goto err;
 	if ((ctx = BN_CTX_new()) == NULL) goto err;
 
 	if (eckey->priv_key == NULL)
 		{
 		priv_key = BN_new();
 		if (priv_key == NULL)
 			goto err;
 		}
 	else
 		priv_key = eckey->priv_key;
 
 	if (!EC_GROUP_get_order(eckey->group, order, ctx))
 		goto err;
 
 	do
 		if (!BN_rand_range(priv_key, order))
 			goto err;
 	while (BN_is_zero(priv_key));
 
 	if (eckey->pub_key == NULL)
 		{
 		pub_key = EC_POINT_new(eckey->group);
 		if (pub_key == NULL)
 			goto err;
 		}
 	else
 		pub_key = eckey->pub_key;
 
 	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
 		goto err;
 
 	eckey->priv_key = priv_key;
 	eckey->pub_key  = pub_key;
 
 	ok=1;
 
 err:	
 	if (order)
 		BN_free(order);
 	if (pub_key  != NULL && eckey->pub_key  == NULL)
 		EC_POINT_free(pub_key);
 	if (priv_key != NULL && eckey->priv_key == NULL)
 		BN_free(priv_key);
 	if (ctx != NULL)
 		BN_CTX_free(ctx);
 	return(ok);
 	}
 
 int EC_KEY_check_key(const EC_KEY *eckey)
 	{
 	int	ok   = 0;
 	BN_CTX	*ctx = NULL;
 	const BIGNUM	*order  = NULL;
 	EC_POINT *point = NULL;
 
 	if (!eckey || !eckey->group || !eckey->pub_key)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
 		goto err;
 		}
 
 	if ((ctx = BN_CTX_new()) == NULL)
 		goto err;
 	if ((point = EC_POINT_new(eckey->group)) == NULL)
 		goto err;
 
 	/* testing whether the pub_key is on the elliptic curve */
-	if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
+	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 	/* testing whether pub_key * order is the point at infinity */
 	order = &eckey->group->order;
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 		goto err;
 		}
 	if (!EC_POINT_is_at_infinity(eckey->group, point))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 		goto err;
 		}
 	/* in case the priv_key is present : 
 	 * check if generator * priv_key == pub_key 
 	 */
 	if (eckey->priv_key)
 		{
 		if (BN_cmp(eckey->priv_key, order) >= 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 			goto err;
 			}
 		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
 			NULL, NULL, ctx))
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 
 			ctx) != 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
 			goto err;
 			}
 		}
 	ok = 1;
 err:
 	if (ctx   != NULL)
 		BN_CTX_free(ctx);
 	if (point != NULL)
 		EC_POINT_free(point);
 	return(ok);
 	}
 
 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
 	{
 	BN_CTX *ctx = NULL;
 	BIGNUM *tx, *ty;
 	EC_POINT *point = NULL;
 	int ok = 0, tmp_nid, is_char_two = 0;
 
 	if (!key || !key->group || !x || !y)
 		{
 		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
 						ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 	ctx = BN_CTX_new();
 	if (!ctx)
 		goto err;
 
 	point = EC_POINT_new(key->group);
 
 	if (!point)
 		goto err;
 
 	tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
 
         if (tmp_nid == NID_X9_62_characteristic_two_field)
 		is_char_two = 1;
 
 	tx = BN_CTX_get(ctx);
 	ty = BN_CTX_get(ctx);
 #ifndef OPENSSL_NO_EC2M
 	if (is_char_two)
 		{
 		if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
 								x, y, ctx))
 			goto err;
 		if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
 								tx, ty, ctx))
 			goto err;
 		}
 	else
 #endif
 		{
 		if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
 								x, y, ctx))
 			goto err;
 		if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
 								tx, ty, ctx))
 			goto err;
 		}
 	/* Check if retrieved coordinates match originals: if not values
 	 * are out of range.
 	 */
 	if (BN_cmp(x, tx) || BN_cmp(y, ty))
 		{
 		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
 			EC_R_COORDINATES_OUT_OF_RANGE);
 		goto err;
 		}
 
 	if (!EC_KEY_set_public_key(key, point))
 		goto err;
 
 	if (EC_KEY_check_key(key) == 0)
 		goto err;
 
 	ok = 1;
 
 	err:
 	if (ctx)
 		BN_CTX_free(ctx);
 	if (point)
 		EC_POINT_free(point);
 	return ok;
 
 	}
 
 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
 	{
 	return key->group;
 	}
 
 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
 	{
 	if (key->group != NULL)
 		EC_GROUP_free(key->group);
 	key->group = EC_GROUP_dup(group);
 	return (key->group == NULL) ? 0 : 1;
 	}
 
 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
 	{
 	return key->priv_key;
 	}
 
 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
 	{
 	if (key->priv_key)
 		BN_clear_free(key->priv_key);
 	key->priv_key = BN_dup(priv_key);
 	return (key->priv_key == NULL) ? 0 : 1;
 	}
 
 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
 	{
 	return key->pub_key;
 	}
 
 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
 	{
 	if (key->pub_key != NULL)
 		EC_POINT_free(key->pub_key);
 	key->pub_key = EC_POINT_dup(pub_key, key->group);
 	return (key->pub_key == NULL) ? 0 : 1;
 	}
 
 unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
 	{
 	return key->enc_flag;
 	}
 
 void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
 	{
 	key->enc_flag = flags;
 	}
 
 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
 	{
 	return key->conv_form;
 	}
 
 void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
 	{
 	key->conv_form = cform;
 	if (key->group != NULL)
 		EC_GROUP_set_point_conversion_form(key->group, cform);
 	}
 
 void *EC_KEY_get_key_method_data(EC_KEY *key,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	void *ret;
 
 	CRYPTO_r_lock(CRYPTO_LOCK_EC);
 	ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	CRYPTO_r_unlock(CRYPTO_LOCK_EC);
 
 	return ret;
 	}
 
 void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *ex_data;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_EC);
 	ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	if (ex_data == NULL)
 		EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
 	CRYPTO_w_unlock(CRYPTO_LOCK_EC);
 
 	return ex_data;
 	}
 
 void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
 	{
 	if (key->group != NULL)
 		EC_GROUP_set_asn1_flag(key->group, flag);
 	}
 
 int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
 	{
 	if (key->group == NULL)
 		return 0;
 	return EC_GROUP_precompute_mult(key->group, ctx);
 	}
 
 int EC_KEY_get_flags(const EC_KEY *key)
 	{
 	return key->flags;
 	}
 
 void EC_KEY_set_flags(EC_KEY *key, int flags)
 	{
 	key->flags |= flags;
 	}
 
 void EC_KEY_clear_flags(EC_KEY *key, int flags)
 	{
 	key->flags &= ~flags;
 	}
Index: releng/10.1/crypto/openssl/crypto/ec/ec_lib.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ec_lib.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ec_lib.c	(revision 284295)
@@ -1,1096 +1,1104 @@
 /* crypto/ec/ec_lib.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Binary polynomial ECC support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #include 
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
 
 
 /* functions for EC_GROUP objects */
 
 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
 	{
 	EC_GROUP *ret;
 
 	if (meth == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
 		return NULL;
 		}
 	if (meth->group_init == 0)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = meth;
 
 	ret->extra_data = NULL;
 
 	ret->generator = NULL;
 	BN_init(&ret->order);
 	BN_init(&ret->cofactor);
 
 	ret->curve_name = 0;	
 	ret->asn1_flag  = 0;
 	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
 
 	ret->seed = NULL;
 	ret->seed_len = 0;
 
 	if (!meth->group_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_GROUP_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_free(group->generator);
 	BN_free(&group->order);
 	BN_free(&group->cofactor);
 
 	if (group->seed)
 		OPENSSL_free(group->seed);
 
 	OPENSSL_free(group);
 	}
  
 
 void EC_GROUP_clear_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_clear_finish != 0)
 		group->meth->group_clear_finish(group);
 	else if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_clear_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_clear_free(group->generator);
 	BN_clear_free(&group->order);
 	BN_clear_free(&group->cofactor);
 
 	if (group->seed)
 		{
 		OPENSSL_cleanse(group->seed, group->seed_len);
 		OPENSSL_free(group->seed);
 		}
 
 	OPENSSL_cleanse(group, sizeof *group);
 	OPENSSL_free(group);
 	}
 
 
 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest->meth->group_copy == 0)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	
 	EC_EX_DATA_free_all_data(&dest->extra_data);
 
 	for (d = src->extra_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	if (src->generator != NULL)
 		{
 		if (dest->generator == NULL)
 			{
 			dest->generator = EC_POINT_new(dest);
 			if (dest->generator == NULL) return 0;
 			}
 		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
 		}
 	else
 		{
 		/* src->generator == NULL */
 		if (dest->generator != NULL)
 			{
 			EC_POINT_clear_free(dest->generator);
 			dest->generator = NULL;
 			}
 		}
 
 	if (!BN_copy(&dest->order, &src->order)) return 0;
 	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
 
 	dest->curve_name = src->curve_name;
 	dest->asn1_flag  = src->asn1_flag;
 	dest->asn1_form  = src->asn1_form;
 
 	if (src->seed)
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = OPENSSL_malloc(src->seed_len);
 		if (dest->seed == NULL)
 			return 0;
 		if (!memcpy(dest->seed, src->seed, src->seed_len))
 			return 0;
 		dest->seed_len = src->seed_len;
 		}
 	else
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = NULL;
 		dest->seed_len = 0;
 		}
 	
 
 	return dest->meth->group_copy(dest, src);
 	}
 
 
 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
 	{
 	EC_GROUP *t = NULL;
 	int ok = 0;
 
 	if (a == NULL) return NULL;
 
 	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
 	if (!EC_GROUP_copy(t, a)) goto err;
 
 	ok = 1;
 
   err:	
 	if (!ok)
 		{
 		if (t) EC_GROUP_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
 	{
 	return group->meth;
 	}
 
 
 int EC_METHOD_get_field_type(const EC_METHOD *meth)
         {
         return meth->field_type;
         }
 
 
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
 	{
 	if (generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
 		return 0   ;
 		}
 
 	if (group->generator == NULL)
 		{
 		group->generator = EC_POINT_new(group);
 		if (group->generator == NULL) return 0;
 		}
 	if (!EC_POINT_copy(group->generator, generator)) return 0;
 
 	if (order != NULL)
 		{ if (!BN_copy(&group->order, order)) return 0; }	
 	else
 		BN_zero(&group->order);
 
 	if (cofactor != NULL)
 		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }	
 	else
 		BN_zero(&group->cofactor);
 
 	return 1;
 	}
 
 
 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
 	{
 	return group->generator;
 	}
 
 
 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
 	{
 	if (!BN_copy(order, &group->order))
 		return 0;
 
 	return !BN_is_zero(order);
 	}
 
 
 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
 	{
 	if (!BN_copy(cofactor, &group->cofactor))
 		return 0;
 
 	return !BN_is_zero(&group->cofactor);
 	}
 
 
 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
 	{
 	group->curve_name = nid;
 	}
 
 
 int EC_GROUP_get_curve_name(const EC_GROUP *group)
 	{
 	return group->curve_name;
 	}
 
 
 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
 	{
 	group->asn1_flag = flag;
 	}
 
 
 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
 	{
 	return group->asn1_flag;
 	}
 
 
 void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 
                                         point_conversion_form_t form)
 	{
 	group->asn1_form = form;
 	}
 
 
 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
 	{
 	return group->asn1_form;
 	}
 
 
 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
 	{
 	if (group->seed)
 		{
 		OPENSSL_free(group->seed);
 		group->seed = NULL;
 		group->seed_len = 0;
 		}
 
 	if (!len || !p)
 		return 1;
 
 	if ((group->seed = OPENSSL_malloc(len)) == NULL)
 		return 0;
 	memcpy(group->seed, p, len);
 	group->seed_len = len;
 
 	return len;
 	}
 
 
 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
 	{
 	return group->seed;
 	}
 
 
 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
 	{
 	return group->seed_len;
 	}
 
 
 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 
 #ifndef OPENSSL_NO_EC2M
 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 #endif
 
 int EC_GROUP_get_degree(const EC_GROUP *group)
 	{
 	if (group->meth->group_get_degree == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_degree(group);
 	}
 
 
 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->group_check_discriminant == 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_check_discriminant(group, ctx);
 	}
 
 
 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
 	{
 	int    r = 0;
 	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
 	BN_CTX *ctx_new = NULL;
 
 	/* compare the field types*/
 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
 	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
 		return 1;
 	/* compare the curve name (if present in both) */
 	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
 	    EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
 		return 1;
 
 	if (!ctx)
 		ctx_new = ctx = BN_CTX_new();
 	if (!ctx)
 		return -1;
 	
 	BN_CTX_start(ctx);
 	a1 = BN_CTX_get(ctx);
 	a2 = BN_CTX_get(ctx);
 	a3 = BN_CTX_get(ctx);
 	b1 = BN_CTX_get(ctx);
 	b2 = BN_CTX_get(ctx);
 	b3 = BN_CTX_get(ctx);
 	if (!b3)
 		{
 		BN_CTX_end(ctx);
 		if (ctx_new)
 			BN_CTX_free(ctx);
 		return -1;
 		}
 
 	/* XXX This approach assumes that the external representation
 	 * of curves over the same field type is the same.
 	 */
 	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
 	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
 		r = 1;
 
 	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
 		r = 1;
 
 	/* XXX EC_POINT_cmp() assumes that the methods are equal */
 	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
 	    EC_GROUP_get0_generator(b), ctx))
 		r = 1;
 
 	if (!r)
 		{
 		/* compare the order and cofactor */
 		if (!EC_GROUP_get_order(a, a1, ctx) ||
 		    !EC_GROUP_get_order(b, b1, ctx) ||
 		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
 		    !EC_GROUP_get_cofactor(b, b2, ctx))
 			{
 			BN_CTX_end(ctx);
 			if (ctx_new)
 				BN_CTX_free(ctx);
 			return -1;
 			}
 		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
 			r = 1;
 		}
 
 	BN_CTX_end(ctx);
 	if (ctx_new)
 		BN_CTX_free(ctx);
 
 	return r;
 	}
 
 
 /* this has 'package' visibility */
 int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return 0;
 
 	for (d = *ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			{
 			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
 			return 0;
 			}
 		}
 
 	if (data == NULL)
 		/* no explicit entry needed */
 		return 1;
 
 	d = OPENSSL_malloc(sizeof *d);
 	if (d == NULL)
 		return 0;
 
 	d->data = data;
 	d->dup_func = dup_func;
 	d->free_func = free_func;
 	d->clear_free_func = clear_free_func;
 
 	d->next = *ex_data;
 	*ex_data = d;
 
 	return 1;
 	}
 
 /* this has 'package' visibility */
 void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	const EC_EXTRA_DATA *d;
 
 	for (d = ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			return d->data;
 		}
 	
 	return NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->clear_free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->clear_free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 
 /* functions for EC_POINT objects */
 
 EC_POINT *EC_POINT_new(const EC_GROUP *group)
 	{
 	EC_POINT *ret;
 
 	if (group == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	if (group->meth->point_init == 0)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = group->meth;
 	
 	if (!ret->meth->point_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_POINT_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_free(point);
 	}
  
 
 void EC_POINT_clear_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_clear_finish != 0)
 		point->meth->point_clear_finish(point);
 	else if (point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_cleanse(point, sizeof *point);
 	OPENSSL_free(point);
 	}
 
 
 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (dest->meth->point_copy == 0)
 		{
 		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	return dest->meth->point_copy(dest, src);
 	}
 
 
 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
 	{
 	EC_POINT *t;
 	int r;
 
 	if (a == NULL) return NULL;
 
 	t = EC_POINT_new(group);
 	if (t == NULL) return(NULL);
 	r = EC_POINT_copy(t, a);
 	if (!r)
 		{
 		EC_POINT_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
 	{
 	return point->meth;
 	}
 
 
 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	if (group->meth->point_set_to_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_to_infinity(group, point);
 	}
 
 
 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 
 #ifndef OPENSSL_NO_EC2M
 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 #endif
 
 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 
 #ifndef OPENSSL_NO_EC2M
 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 #endif
 
 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->add == 0)
 		{
 		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->add(group, r, a, b, ctx);
 	}
 
 
 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->dbl == 0)
 		{
 		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth))
 		{
 		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->dbl(group, r, a, ctx);
 	}
 
 
 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->invert == 0)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != a->meth)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->invert(group, a, ctx);
 	}
 
 
 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	if (group->meth->is_at_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_at_infinity(group, point);
 	}
 
 
-int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+/*
+ * Check whether an EC_POINT is on the curve or not. Note that the return
+ * value for this function should NOT be treated as a boolean. Return values:
+ *  1: The point is on the curve
+ *  0: The point is not on the curve
+ * -1: An error occurred
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+                         BN_CTX *ctx)
 	{
 	if (group->meth->is_on_curve == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_on_curve(group, point, ctx);
 	}
 
 
 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->point_cmp == 0)
 		{
 		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return -1;
 		}
 	if ((group->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
 		return -1;
 		}
 	return group->meth->point_cmp(group, a, b, ctx);
 	}
 
 
 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (group->meth->make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->make_affine(group, point, ctx);
 	}
 
 
 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	size_t i;
 
 	if (group->meth->points_make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	for (i = 0; i < num; i++)
 		{
 		if (group->meth != points[i]->meth)
 			{
 			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 			return 0;
 			}
 		}
 	return group->meth->points_make_affine(group, num, points, ctx);
 	}
 
 
 /* Functions for point multiplication.
  *
  * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
  * otherwise we dispatch through methods.
  */
 
 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
 	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
 
 	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
 	}
 
 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
 	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
 	{
 	/* just a convenient interface to EC_POINTs_mul() */
 
 	const EC_POINT *points[1];
 	const BIGNUM *scalars[1];
 
 	points[0] = point;
 	scalars[0] = p_scalar;
 
 	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
 	}
 
 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_precompute_mult(group, ctx);
 
 	if (group->meth->precompute_mult != 0)
 		return group->meth->precompute_mult(group, ctx);
 	else
 		return 1; /* nothing to do, so report success */
 	}
 
 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_have_precompute_mult(group);
 
 	if (group->meth->have_precompute_mult != 0)
 		return group->meth->have_precompute_mult(group);
 	else
 		return 0; /* cannot tell whether precomputation has been performed */
 	}
Index: releng/10.1/crypto/openssl/crypto/ec/ecp_oct.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ecp_oct.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ecp_oct.c	(revision 284295)
@@ -1,433 +1,434 @@
 /* crypto/ec/ecp_oct.c */
 /* Includes code written by Lenka Fibikova 
  * for the OpenSSL project. 
  * Includes code written by Bodo Moeller for the OpenSSL project.
 */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
  * and contributed to the OpenSSL project.
  */
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp1, *tmp2, *x, *y;
 	int ret = 0;
 
 	/* clear error queue*/
 	ERR_clear_error();
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	y_bit = (y_bit != 0);
 
 	BN_CTX_start(ctx);
 	tmp1 = BN_CTX_get(ctx);
 	tmp2 = BN_CTX_get(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	/* Recover y.  We have a Weierstrass equation
 	 *     y^2 = x^3 + a*x + b,
 	 * so  y  is one of the square roots of  x^3 + a*x + b.
 	 */
 
 	/* tmp1 := x^3 */
 	if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
 	if (group->meth->field_decode == 0)
 		{
 		/* field_{sqr,mul} work on standard representation */
 		if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
 		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
 		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + a*x */
 	if (group->a_is_minus3)
 		{
 		if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
 		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
 		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (group->meth->field_decode)
 			{
 			if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
 			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
 			}
 		else
 			{
 			/* field_mul works on standard representation */
 			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
 			}
 		
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + b */
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
 		}
 	
 	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
 		{
 		unsigned long err = ERR_peek_last_error();
 		
 		if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
 			{
 			ERR_clear_error();
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			}
 		else
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
 		goto err;
 		}
 
 	if (y_bit != BN_is_odd(y))
 		{
 		if (BN_is_zero(y))
 			{
 			int kron;
 
 			kron = BN_kronecker(x, &group->field, ctx);
 			if (kron == -2) goto err;
 
 			if (kron == 1)
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
 			else
 				/* BN_mod_sqrt() should have cought this error (not a square) */
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			goto err;
 			}
 		if (!BN_usub(y, &group->field, y)) goto err;
 		}
 	if (y_bit != BN_is_odd(y))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y;
 	size_t field_len, i, skip;
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = BN_num_bytes(&group->field);
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		if (y == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
 			buf[0] = form + 1;
 		else
 			buf[0] = form;
 	
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = BN_num_bytes(&group->field);
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (y_bit != BN_is_odd(y))
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
Index: releng/10.1/crypto/openssl/crypto/ec/ectest.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/ec/ectest.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/ec/ectest.c	(revision 284295)
@@ -1,1525 +1,1525 @@
 /* crypto/ec/ectest.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * The elliptic curve binary polynomial software is originally written by 
  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 
 #include 
 #include 
 #ifdef FLAT_INC
 #include "e_os.h"
 #else
 #include "../e_os.h"
 #endif
 #include 
 #include 
 
 
 #ifdef OPENSSL_NO_EC
 int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
 #else
 
 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
 #if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
 /* suppress "too big too optimize" warning */
 #pragma warning(disable:4959)
 #endif
 
 #define ABORT do { \
 	fflush(stdout); \
 	fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
 	ERR_print_errors_fp(stderr); \
 	EXIT(1); \
 } while (0)
 
 #define TIMING_BASE_PT 0
 #define TIMING_RAND_PT 1
 #define TIMING_SIMUL 2
 
 #if 0
 static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
 	{
 	clock_t clck;
 	int i, j;
 	BIGNUM *s;
 	BIGNUM *r[10], *r0[10];
 	EC_POINT *P;
 		
 	s = BN_new();
 	if (s == NULL) ABORT;
 
 	fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
 	if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
 	fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
 	fflush(stdout);
 
 	P = EC_POINT_new(group);
 	if (P == NULL) ABORT;
 	EC_POINT_copy(P, EC_GROUP_get0_generator(group));
 
 	for (i = 0; i < 10; i++)
 		{
 		if ((r[i] = BN_new()) == NULL) ABORT;
 		if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
 		if (type != TIMING_BASE_PT)
 			{
 			if ((r0[i] = BN_new()) == NULL) ABORT;
 			if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
 			}
 		}
 
 	clck = clock();
 	for (i = 0; i < 10; i++)
 		{
 		for (j = 0; j < 10; j++)
 			{
 			if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, 
 				(type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
 			}
 		}
 	clck = clock() - clck;
 
 	fprintf(stdout, "\n");
 
 #ifdef CLOCKS_PER_SEC
 	/* "To determine the time in seconds, the value returned
 	 * by the clock function should be divided by the value
 	 * of the macro CLOCKS_PER_SEC."
 	 *                                       -- ISO/IEC 9899 */
 #	define UNIT "s"
 #else
 	/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
 	 *                            -- cc on NeXTstep/OpenStep */
 #	define UNIT "units"
 #	define CLOCKS_PER_SEC 1
 #endif
 
 	if (type == TIMING_BASE_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"base point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_RAND_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"random point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_SIMUL) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
 	}
 	fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
 
 	EC_POINT_free(P);
 	BN_free(s);
 	for (i = 0; i < 10; i++)
 		{
 		BN_free(r[i]);
 		if (type != TIMING_BASE_PT) BN_free(r0[i]);
 		}
 	}
 #endif
 
 /* test multiplication with group order, long and negative scalars */
 static void group_order_tests(EC_GROUP *group)
 	{
 	BIGNUM *n1, *n2, *order;
 	EC_POINT *P = EC_POINT_new(group);
 	EC_POINT *Q = EC_POINT_new(group);
 	BN_CTX *ctx = BN_CTX_new();
 	int i;
 
 	n1 = BN_new(); n2 = BN_new(); order = BN_new();
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, order, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 	fprintf(stdout, "long/negative scalar tests ");
         for (i = 1; i <= 2; i++)
 		{
 		const BIGNUM *scalars[6];
 		const EC_POINT *points[6];
 
 		fprintf(stdout, i == 1 ?
 			"allowing precomputation ... " :
 			"without precomputation ... ");
 		if (!BN_set_word(n1, i)) ABORT;
 		/* If i == 1, P will be the predefined generator for which
 		 * EC_GROUP_precompute_mult has set up precomputation. */
 		if (!EC_POINT_mul(group, P, n1, NULL, NULL, ctx)) ABORT;
 
 		if (!BN_one(n1)) ABORT;
 		/* n1 = 1 - order */
 		if (!BN_sub(n1, n1, order)) ABORT;
 		if (!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
 
 		/* n2 = 1 + order */
 		if (!BN_add(n2, order, BN_value_one())) ABORT;
 		if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
 
 		/* n2 = (1 - order) * (1 + order) = 1 - order^2 */
 		if (!BN_mul(n2, n1, n2, ctx)) ABORT;
 		if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
 
 		/* n2 = order^2 - 1 */
 		BN_set_negative(n2, 0);
 		if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
 		/* Add P to verify the result. */
 		if (!EC_POINT_add(group, Q, Q, P, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 
 		/* Exercise EC_POINTs_mul, including corner cases. */
 		if (EC_POINT_is_at_infinity(group, P)) ABORT;
 		scalars[0] = n1; points[0] = Q; /* => infinity */
 		scalars[1] = n2; points[1] = P; /* => -P */
 		scalars[2] = n1; points[2] = Q; /* => infinity */
 		scalars[3] = n2; points[3] = Q; /* => infinity */
 		scalars[4] = n1; points[4] = P; /* => P */
 		scalars[5] = n2; points[5] = Q; /* => infinity */
 		if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 		}
 	fprintf(stdout, "ok\n");
 
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	BN_free(n1);
 	BN_free(n2);
 	BN_free(order);
 	BN_CTX_free(ctx);
 	}
 
 static void prime_field_tests(void)
 	{
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "17")) ABORT;
 	if (!BN_hex2bn(&a, "1")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
 	                                             * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	if (!x || !y || !z) ABORT;
 
 	if (!BN_hex2bn(&x, "D")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 
 #if 0 /* optional */
 		{
 			EC_POINT *points[3];
 		
 			points[0] = R;
 			points[1] = Q;
 			points[2] = P;
 			if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
 		}
 #endif
 
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
 	fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, ", Y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, ", Z = 0x");
 	BN_print_fp(stdout, z);
 	fprintf(stdout, "\n");
 
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
 	 * -- not a NIST curve, but commonly used */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
 	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 160) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	group_order_tests(group);
 
 	if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_160, group)) ABORT;
 
 
 	/* Curve P-192 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-192 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 192) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	group_order_tests(group);
 
 	if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_192, group)) ABORT;
 
 
 	/* Curve P-224 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
 	if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-224 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 224) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	group_order_tests(group);
 
 	if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_224, group)) ABORT;
 
 
 	/* Curve P-256 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
 		"84F3B9CAC2FC632551")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-256 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 256) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	group_order_tests(group);
 
 	if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_256, group)) ABORT;
 
 
 	/* Curve P-384 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
 		"120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
 		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-384 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"
 		"7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 384) ABORT;
 	fprintf(stdout, " ok\n");
 
 	group_order_tests(group);
 
 	if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_384, group)) ABORT;
 
 
 	/* Curve P-521 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"
 		"315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"
 		"DF883D2C34F1EF451FD46B503F00")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"
 		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
 		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
 		"C9B8899C47AEBB6FB71E91386409")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-521 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"
 		"B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"
 		"7086A272C24088BE94769FD16650")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 521) ABORT;
 	fprintf(stdout, " ok\n");
 
  	group_order_tests(group);
 
 	if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_521, group)) ABORT;
 
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[4];
 		const BIGNUM *scalars[4];
 		BIGNUM scalar3;
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 		points[3] = Q;
 
 		if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		BN_init(&scalar3);
 		BN_zero(&scalar3);
 		scalars[3] = &scalar3;
 
 		if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 
 		BN_free(&scalar3);
 	}
 
 
 #if 0
 	timings(P_160, TIMING_BASE_PT, ctx);
 	timings(P_160, TIMING_RAND_PT, ctx);
 	timings(P_160, TIMING_SIMUL, ctx);
 	timings(P_192, TIMING_BASE_PT, ctx);
 	timings(P_192, TIMING_RAND_PT, ctx);
 	timings(P_192, TIMING_SIMUL, ctx);
 	timings(P_224, TIMING_BASE_PT, ctx);
 	timings(P_224, TIMING_RAND_PT, ctx);
 	timings(P_224, TIMING_SIMUL, ctx);
 	timings(P_256, TIMING_BASE_PT, ctx);
 	timings(P_256, TIMING_RAND_PT, ctx);
 	timings(P_256, TIMING_SIMUL, ctx);
 	timings(P_384, TIMING_BASE_PT, ctx);
 	timings(P_384, TIMING_RAND_PT, ctx);
 	timings(P_384, TIMING_SIMUL, ctx);
 	timings(P_521, TIMING_BASE_PT, ctx);
 	timings(P_521, TIMING_RAND_PT, ctx);
 	timings(P_521, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z);
 
 	if (P_160) EC_GROUP_free(P_160);
 	if (P_192) EC_GROUP_free(P_192);
 	if (P_224) EC_GROUP_free(P_224);
 	if (P_256) EC_GROUP_free(P_256);
 	if (P_384) EC_GROUP_free(P_384);
 	if (P_521) EC_GROUP_free(P_521);
 
 	}
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n"); \
 	/* G_y value taken from the standard: */ \
 	if (!BN_hex2bn(&z, _y)) ABORT; \
 	if (0 != BN_cmp(y, z)) ABORT;
 #else 
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!BN_hex2bn(&y, _y)) ABORT; \
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n");
 #endif
 
 #define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&p, _p)) ABORT; \
 	if (!BN_hex2bn(&a, _a)) ABORT; \
 	if (!BN_hex2bn(&b, _b)) ABORT; \
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \
 	CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	fprintf(stdout, "verify degree ..."); \
 	if (EC_GROUP_get_degree(group) != _degree) ABORT; \
 	fprintf(stdout, " ok\n"); \
 	group_order_tests(group); \
 	if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
 	if (!EC_GROUP_copy(_variable, group)) ABORT; \
 
 #ifndef OPENSSL_NO_EC2M
 
 static void char2_field_tests(void)
 	{
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
 	EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z, *cof;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "13")) ABORT;
 	if (!BN_hex2bn(&a, "3")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
 	                                                * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n(0x... means binary polynomial)\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	cof = BN_new();
 	if (!x || !y || !z || !cof) ABORT;
 
 	if (!BN_hex2bn(&x, "6")) ABORT;
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
 #else
 	if (!BN_hex2bn(&y, "8")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 
 	fprintf(stdout, "\n");
 	
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve K-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"1",
 		"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
 		"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
 		1,
 		"04000000000000000000020108A2E0CC0D99F8A5EF",
 		"2",
 		163,
 		C2_K163
 		);
 
 	/* Curve B-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"020A601907B8C953CA1481EB10512F78744A3205FD",
 		"03F0EBA16286A2D57EA0991168D4994637E8343E36",
 		"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
 		1,
 		"040000000000000000000292FE77E70C12A4234C33",
 		"2",
 		163,
 		C2_B163
 		);
 
 	/* Curve K-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"0",
 		"1",
 		"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
 		"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
 		0,
 		"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
 		"4",
 		233,
 		C2_K233
 		);
 
 	/* Curve B-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"000000000000000000000000000000000000000000000000000000000001",
 		"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
 		"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
 		"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
 		1,
 		"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
 		"2",
 		233,
 		C2_B233
 		);
 
 	/* Curve K-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"0",
 		"1",
 		"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
 		"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
 		0,
 		"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
 		"4",
 		283,
 		C2_K283
 		);
 
 	/* Curve B-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"000000000000000000000000000000000000000000000000000000000000000000000001",
 		"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
 		"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
 		"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
 		"2",
 		283,
 		C2_B283
 		);
 
 	/* Curve K-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"0",
 		"1",
 		"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
 		"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
 		1,
 		"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
 		"4",
 		409,
 		C2_K409
 		);
 
 	/* Curve B-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
 		"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
 		"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
 		1,
 		"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
 		"2",
 		409,
 		C2_B409
 		);
 
 	/* Curve K-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"0",
 		"1",
 		"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
 		"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
 		0,
 		"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
 		"4",
 		571,
 		C2_K571
 		);
 
 	/* Curve B-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
 		"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
 		"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
 		"2",
 		571,
 		C2_B571
 		);
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[3];
 		const BIGNUM *scalars[3];
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 	}
 
 
 #if 0
 	timings(C2_K163, TIMING_BASE_PT, ctx);
 	timings(C2_K163, TIMING_RAND_PT, ctx);
 	timings(C2_K163, TIMING_SIMUL, ctx);
 	timings(C2_B163, TIMING_BASE_PT, ctx);
 	timings(C2_B163, TIMING_RAND_PT, ctx);
 	timings(C2_B163, TIMING_SIMUL, ctx);
 	timings(C2_K233, TIMING_BASE_PT, ctx);
 	timings(C2_K233, TIMING_RAND_PT, ctx);
 	timings(C2_K233, TIMING_SIMUL, ctx);
 	timings(C2_B233, TIMING_BASE_PT, ctx);
 	timings(C2_B233, TIMING_RAND_PT, ctx);
 	timings(C2_B233, TIMING_SIMUL, ctx);
 	timings(C2_K283, TIMING_BASE_PT, ctx);
 	timings(C2_K283, TIMING_RAND_PT, ctx);
 	timings(C2_K283, TIMING_SIMUL, ctx);
 	timings(C2_B283, TIMING_BASE_PT, ctx);
 	timings(C2_B283, TIMING_RAND_PT, ctx);
 	timings(C2_B283, TIMING_SIMUL, ctx);
 	timings(C2_K409, TIMING_BASE_PT, ctx);
 	timings(C2_K409, TIMING_RAND_PT, ctx);
 	timings(C2_K409, TIMING_SIMUL, ctx);
 	timings(C2_B409, TIMING_BASE_PT, ctx);
 	timings(C2_B409, TIMING_RAND_PT, ctx);
 	timings(C2_B409, TIMING_SIMUL, ctx);
 	timings(C2_K571, TIMING_BASE_PT, ctx);
 	timings(C2_K571, TIMING_RAND_PT, ctx);
 	timings(C2_K571, TIMING_SIMUL, ctx);
 	timings(C2_B571, TIMING_BASE_PT, ctx);
 	timings(C2_B571, TIMING_RAND_PT, ctx);
 	timings(C2_B571, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z); BN_free(cof);
 
 	if (C2_K163) EC_GROUP_free(C2_K163);
 	if (C2_B163) EC_GROUP_free(C2_B163);
 	if (C2_K233) EC_GROUP_free(C2_K233);
 	if (C2_B233) EC_GROUP_free(C2_B233);
 	if (C2_K283) EC_GROUP_free(C2_K283);
 	if (C2_B283) EC_GROUP_free(C2_B283);
 	if (C2_K409) EC_GROUP_free(C2_K409);
 	if (C2_B409) EC_GROUP_free(C2_B409);
 	if (C2_K571) EC_GROUP_free(C2_K571);
 	if (C2_B571) EC_GROUP_free(C2_B571);
 
 	}
 #endif
 
 static void internal_curve_test(void)
 	{
 	EC_builtin_curve *curves = NULL;
 	size_t crv_len = 0, n = 0;
 	int    ok = 1;
 
 	crv_len = EC_get_builtin_curves(NULL, 0);
 
 	curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
 
 	if (curves == NULL)
 		return;
 
 	if (!EC_get_builtin_curves(curves, crv_len))
 		{
 		OPENSSL_free(curves);
 		return;
 		}
 
 	fprintf(stdout, "testing internal curves: ");
 		
 	for (n = 0; n < crv_len; n++)
 		{
 		EC_GROUP *group = NULL;
 		int nid = curves[n].nid;
 		if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			/* try next curve */
 			continue;
 			}
 		if (!EC_GROUP_check(group, NULL))
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_check() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			EC_GROUP_free(group);
 			/* try the next curve */
 			continue;
 			}
 		fprintf(stdout, ".");
 		fflush(stdout);
 		EC_GROUP_free(group);
 		}
 	if (ok)
 		fprintf(stdout, " ok\n\n");
 	else
 		{
 		fprintf(stdout, " failed\n\n");
 		ABORT;
 		}
 	OPENSSL_free(curves);
 	return;
 	}
 
 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
 /* nistp_test_params contains magic numbers for testing our optimized
  * implementations of several NIST curves with characteristic > 3. */
 struct nistp_test_params
 	{
 	const EC_METHOD* (*meth) ();
 	int degree;
 	/* Qx, Qy and D are taken from
 	 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
 	 * Otherwise, values are standard curve parameters from FIPS 180-3 */
 	const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
 	};
 
 static const struct nistp_test_params nistp_tests_params[] =
 	{
 		{
 		/* P-224 */
 		EC_GFp_nistp224_method,
 		224,
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* p */
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* a */
 		"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* b */
 		"E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", /* Qx */
 		"4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", /* Qy */
 		"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */
 		"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */
 		"3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", /* d */
 		},
 		{
 		/* P-256 */
 		EC_GFp_nistp256_method,
 		256,
 		"ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", /* p */
 		"ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", /* a */
 		"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", /* b */
 		"b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", /* Qx */
 		"3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", /* Qy */
 		"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", /* Gx */
 		"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", /* Gy */
 		"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", /* order */
 		"c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", /* d */
 		},
 		{
 		/* P-521 */
 		EC_GFp_nistp521_method,
 		521,
 		"1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", /* p */
 		"1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", /* a */
 		"051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", /* b */
 		"0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", /* Qx */
 		"0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", /* Qy */
 		"c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", /* Gx */
 		"11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", /* Gy */
 		"1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", /* order */
 		"0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", /* d */
 		},
 	};
 
 static void nistp_single_test(const struct nistp_test_params *test)
 	{
 	BN_CTX *ctx;
 	BIGNUM *p, *a, *b, *x, *y, *n, *m, *order;
 	EC_GROUP *NISTP;
 	EC_POINT *G, *P, *Q, *Q_CHECK;
 
 	fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", test->degree);
 	ctx = BN_CTX_new();
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	x = BN_new(); y = BN_new();
 	m = BN_new(); n = BN_new(); order = BN_new();
 
 	NISTP = EC_GROUP_new(test->meth());
 	if(!NISTP) ABORT;
 	if (!BN_hex2bn(&p, test->p)) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, test->a)) ABORT;
 	if (!BN_hex2bn(&b, test->b)) ABORT;
 	if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) ABORT;
 	G = EC_POINT_new(NISTP);
 	P = EC_POINT_new(NISTP);
 	Q = EC_POINT_new(NISTP);
 	Q_CHECK = EC_POINT_new(NISTP);
 	if(!BN_hex2bn(&x, test->Qx)) ABORT;
 	if(!BN_hex2bn(&y, test->Qy)) ABORT;
 	if(!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) ABORT;
 	if (!BN_hex2bn(&x, test->Gx)) ABORT;
 	if (!BN_hex2bn(&y, test->Gy)) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) ABORT;
 	if (!BN_hex2bn(&order, test->order)) ABORT;
 	if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
 
 	fprintf(stdout, "verify degree ... ");
 	if (EC_GROUP_get_degree(NISTP) != test->degree) ABORT;
 	fprintf(stdout, "ok\n");
 
 	fprintf(stdout, "NIST test vectors ... ");
 	if (!BN_hex2bn(&n, test->d)) ABORT;
 	/* fixed point multiplication */
 	EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 	/* random point multiplication */
 	EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 
 	/* set generator to P = 2*G, where G is the standard generator */
 	if (!EC_POINT_dbl(NISTP, P, G, ctx)) ABORT;
 	if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) ABORT;
 	/* set the scalar to m=n/2, where n is the NIST test scalar */
 	if (!BN_rshift(m, n, 1)) ABORT;
 
 	/* test the non-standard generator */
 	/* fixed point multiplication */
 	EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 	/* random point multiplication */
 	EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 
 	/* now repeat all tests with precomputation */
 	if (!EC_GROUP_precompute_mult(NISTP, ctx)) ABORT;
 
 	/* fixed point multiplication */
 	EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 	/* random point multiplication */
 	EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 
 	/* reset generator */
 	if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
 	/* fixed point multiplication */
 	EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 	/* random point multiplication */
 	EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
 	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
 
 	fprintf(stdout, "ok\n");
 	group_order_tests(NISTP);
 #if 0
 	timings(NISTP, TIMING_BASE_PT, ctx);
 	timings(NISTP, TIMING_RAND_PT, ctx);
 #endif
 	EC_GROUP_free(NISTP);
 	EC_POINT_free(G);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(Q_CHECK);
 	BN_free(n);
 	BN_free(m);
 	BN_free(p);
 	BN_free(a);
 	BN_free(b);
 	BN_free(x);
 	BN_free(y);
 	BN_free(order);
 	BN_CTX_free(ctx);
 	}
 
 static void nistp_tests()
 	{
 	unsigned i;
 
 	for (i = 0; i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); i++)
 		{
 		nistp_single_test(&nistp_tests_params[i]);
 		}
 	}
 #endif
 
 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
 
 int main(int argc, char *argv[])
 	{	
 	
 	/* enable memory leak checking unless explicitly disabled */
 	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
 		{
 		CRYPTO_malloc_debug_init();
 		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
 		}
 	else
 		{
 		/* OPENSSL_DEBUG_MEMORY=off */
 		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
 		}
 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 	ERR_load_crypto_strings();
 
 	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
 
 	prime_field_tests();
 	puts("");
 #ifndef OPENSSL_NO_EC2M
 	char2_field_tests();
 #endif
 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
 	nistp_tests();
 #endif
 	/* test the internal curves */
 	internal_curve_test();
 
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_cleanup();
 #endif
 	CRYPTO_cleanup_all_ex_data();
 	ERR_free_strings();
 	ERR_remove_thread_state(NULL);
 	CRYPTO_mem_leaks_fp(stderr);
 	
 	return 0;
 	}
 #endif
Index: releng/10.1/crypto/openssl/crypto/evp/e_aes.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/evp/e_aes.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/evp/e_aes.c	(revision 284295)
@@ -1,1375 +1,1376 @@
 /* ====================================================================
  * Copyright (c) 2001-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  */
 
 #include 
 #ifndef OPENSSL_NO_AES
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include "evp_locl.h"
 #ifndef OPENSSL_FIPS
 #include "modes_lcl.h"
 #include 
 
 typedef struct
 	{
 	AES_KEY ks;
 	block128_f block;
 	union {
 		cbc128_f cbc;
 		ctr128_f ctr;
 	} stream;
 	} EVP_AES_KEY;
 
 typedef struct
 	{
 	AES_KEY ks;		/* AES key schedule to use */
 	int key_set;		/* Set if key initialised */
 	int iv_set;		/* Set if an iv is set */
 	GCM128_CONTEXT gcm;
 	unsigned char *iv;	/* Temporary IV store */
 	int ivlen;		/* IV length */
 	int taglen;
 	int iv_gen;		/* It is OK to generate IVs */
 	int tls_aad_len;	/* TLS AAD length */
 	ctr128_f ctr;
 	} EVP_AES_GCM_CTX;
 
 typedef struct
 	{
 	AES_KEY ks1, ks2;	/* AES key schedules to use */
 	XTS128_CONTEXT xts;
 	void     (*stream)(const unsigned char *in,
 			unsigned char *out, size_t length,
 			const AES_KEY *key1, const AES_KEY *key2,
 			const unsigned char iv[16]);
 	} EVP_AES_XTS_CTX;
 
 typedef struct
 	{
 	AES_KEY ks;		/* AES key schedule to use */
 	int key_set;		/* Set if key initialised */
 	int iv_set;		/* Set if an iv is set */
 	int tag_set;		/* Set if tag is valid */
 	int len_set;		/* Set if message length set */
 	int L, M;		/* L and M parameters from RFC3610 */
 	CCM128_CONTEXT ccm;
 	ccm128_f str;
 	} EVP_AES_CCM_CTX;
 
 #define MAXBITCHUNK	((size_t)1<<(sizeof(size_t)*8-4))
 
 #ifdef VPAES_ASM
 int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
 			AES_KEY *key);
 int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
 			AES_KEY *key);
 
 void vpaes_encrypt(const unsigned char *in, unsigned char *out,
 			const AES_KEY *key);
 void vpaes_decrypt(const unsigned char *in, unsigned char *out,
 			const AES_KEY *key);
 
 void vpaes_cbc_encrypt(const unsigned char *in,
 			unsigned char *out,
 			size_t length,
 			const AES_KEY *key,
 			unsigned char *ivec, int enc);
 #endif
 #ifdef BSAES_ASM
 void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
 			size_t length, const AES_KEY *key,
 			unsigned char ivec[16], int enc);
 void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
 			size_t len, const AES_KEY *key,
 			const unsigned char ivec[16]);
 void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
 			size_t len, const AES_KEY *key1,
 			const AES_KEY *key2, const unsigned char iv[16]);
 void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
 			size_t len, const AES_KEY *key1,
 			const AES_KEY *key2, const unsigned char iv[16]);
 #endif
 #ifdef AES_CTR_ASM
 void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
 			size_t blocks, const AES_KEY *key,
 			const unsigned char ivec[AES_BLOCK_SIZE]);
 #endif
 #ifdef AES_XTS_ASM
 void AES_xts_encrypt(const char *inp,char *out,size_t len,
 			const AES_KEY *key1, const AES_KEY *key2,
 			const unsigned char iv[16]);
 void AES_xts_decrypt(const char *inp,char *out,size_t len,
 			const AES_KEY *key1, const AES_KEY *key2,
 			const unsigned char iv[16]);
 #endif
 
 #if	defined(AES_ASM) && !defined(I386_ONLY) &&	(  \
 	((defined(__i386)	|| defined(__i386__)	|| \
 	  defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
 	defined(__x86_64)	|| defined(__x86_64__)	|| \
 	defined(_M_AMD64)	|| defined(_M_X64)	|| \
 	defined(__INTEL__)				)
 
 extern unsigned int OPENSSL_ia32cap_P[2];
 
 #ifdef VPAES_ASM
 #define VPAES_CAPABLE	(OPENSSL_ia32cap_P[1]&(1<<(41-32)))
 #endif
 #ifdef BSAES_ASM
 #define BSAES_CAPABLE	(OPENSSL_ia32cap_P[1]&(1<<(41-32)))
 #endif
 /*
  * AES-NI section
  */
 #define	AESNI_CAPABLE	(OPENSSL_ia32cap_P[1]&(1<<(57-32)))
 
 int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
 			AES_KEY *key);
 int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
 			AES_KEY *key);
 
 void aesni_encrypt(const unsigned char *in, unsigned char *out,
 			const AES_KEY *key);
 void aesni_decrypt(const unsigned char *in, unsigned char *out,
 			const AES_KEY *key);
 
 void aesni_ecb_encrypt(const unsigned char *in,
 			unsigned char *out,
 			size_t length,
 			const AES_KEY *key,
 			int enc);
 void aesni_cbc_encrypt(const unsigned char *in,
 			unsigned char *out,
 			size_t length,
 			const AES_KEY *key,
 			unsigned char *ivec, int enc);
 
 void aesni_ctr32_encrypt_blocks(const unsigned char *in,
 			unsigned char *out,
 			size_t blocks,
 			const void *key,
 			const unsigned char *ivec);
 
 void aesni_xts_encrypt(const unsigned char *in,
 			unsigned char *out,
 			size_t length,
 			const AES_KEY *key1, const AES_KEY *key2,
 			const unsigned char iv[16]);
 
 void aesni_xts_decrypt(const unsigned char *in,
 			unsigned char *out,
 			size_t length,
 			const AES_KEY *key1, const AES_KEY *key2,
 			const unsigned char iv[16]);
 
 void aesni_ccm64_encrypt_blocks (const unsigned char *in,
 			unsigned char *out,
 			size_t blocks,
 			const void *key,
 			const unsigned char ivec[16],
 			unsigned char cmac[16]);
 
 void aesni_ccm64_decrypt_blocks (const unsigned char *in,
 			unsigned char *out,
 			size_t blocks,
 			const void *key,
 			const unsigned char ivec[16],
 			unsigned char cmac[16]);
 
 static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 		   const unsigned char *iv, int enc)
 	{
 	int ret, mode;
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	mode = ctx->cipher->flags & EVP_CIPH_MODE;
 	if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
 	    && !enc)
 		{ 
 		ret = aesni_set_decrypt_key(key, ctx->key_len*8, ctx->cipher_data);
 		dat->block	= (block128_f)aesni_decrypt;
 		dat->stream.cbc	= mode==EVP_CIPH_CBC_MODE ?
 					(cbc128_f)aesni_cbc_encrypt :
 					NULL;
 		}
 	else	{
 		ret = aesni_set_encrypt_key(key, ctx->key_len*8, ctx->cipher_data);
 		dat->block	= (block128_f)aesni_encrypt;
 		if (mode==EVP_CIPH_CBC_MODE)
 			dat->stream.cbc	= (cbc128_f)aesni_cbc_encrypt;
 		else if (mode==EVP_CIPH_CTR_MODE)
 			dat->stream.ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
 		else
 			dat->stream.cbc = NULL;
 		}
 
 	if(ret < 0)
 		{
 		EVPerr(EVP_F_AESNI_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
 		return 0;
 		}
 
 	return 1;
 	}
 
 static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in, size_t len)
 {
 	aesni_cbc_encrypt(in,out,len,ctx->cipher_data,ctx->iv,ctx->encrypt);
 
 	return 1;
 }
 
 static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in, size_t len)
 {
 	size_t	bl = ctx->cipher->block_size;
 
 	if (lencipher_data,ctx->encrypt);
 
 	return 1;
 }
 
 #define aesni_ofb_cipher aes_ofb_cipher
 static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len);
 
 #define aesni_cfb_cipher aes_cfb_cipher
 static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len);
 
 #define aesni_cfb8_cipher aes_cfb8_cipher
 static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len);
 
 #define aesni_cfb1_cipher aes_cfb1_cipher
 static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len);
 
 #define aesni_ctr_cipher aes_ctr_cipher
 static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len);
 
 static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 	if (key)
 		{
 		aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
 		CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
 				(block128_f)aesni_encrypt);
 		gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
 		/* If we have an iv can set it directly, otherwise use
 		 * saved IV.
 		 */
 		if (iv == NULL && gctx->iv_set)
 			iv = gctx->iv;
 		if (iv)
 			{
 			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
 			gctx->iv_set = 1;
 			}
 		gctx->key_set = 1;
 		}
 	else
 		{
 		/* If key set use IV, otherwise copy */
 		if (gctx->key_set)
 			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
 		else
 			memcpy(gctx->iv, iv, gctx->ivlen);
 		gctx->iv_set = 1;
 		gctx->iv_gen = 0;
 		}
 	return 1;
 	}
 
 #define aesni_gcm_cipher aes_gcm_cipher
 static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len);
 
 static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 
 	if (key)
 		{
 		/* key_len is two AES keys */
 		if (enc)
 			{
 			aesni_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)aesni_encrypt;
 			xctx->stream = aesni_xts_encrypt;
 			}
 		else
 			{
 			aesni_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)aesni_decrypt;
 			xctx->stream = aesni_xts_decrypt;
 			}
 
 		aesni_set_encrypt_key(key + ctx->key_len/2,
 						ctx->key_len * 4, &xctx->ks2);
 		xctx->xts.block2 = (block128_f)aesni_encrypt;
 
 		xctx->xts.key1 = &xctx->ks1;
 		}
 
 	if (iv)
 		{
 		xctx->xts.key2 = &xctx->ks2;
 		memcpy(ctx->iv, iv, 16);
 		}
 
 	return 1;
 	}
 
 #define aesni_xts_cipher aes_xts_cipher
 static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len);
 
 static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 	if (key)
 		{
 		aesni_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
 		CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
 					&cctx->ks, (block128_f)aesni_encrypt);
 		cctx->str = enc?(ccm128_f)aesni_ccm64_encrypt_blocks :
 				(ccm128_f)aesni_ccm64_decrypt_blocks;
 		cctx->key_set = 1;
 		}
 	if (iv)
 		{
 		memcpy(ctx->iv, iv, 15 - cctx->L);
 		cctx->iv_set = 1;
 		}
 	return 1;
 	}
 
 #define aesni_ccm_cipher aes_ccm_cipher
 static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len);
 
 #define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
 static const EVP_CIPHER aesni_##keylen##_##mode = { \
 	nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aesni_init_key,			\
 	aesni_##mode##_cipher,		\
 	NULL,				\
 	sizeof(EVP_AES_KEY),		\
 	NULL,NULL,NULL,NULL }; \
 static const EVP_CIPHER aes_##keylen##_##mode = { \
 	nid##_##keylen##_##nmode,blocksize,	\
 	keylen/8,ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aes_init_key,			\
 	aes_##mode##_cipher,		\
 	NULL,				\
 	sizeof(EVP_AES_KEY),		\
 	NULL,NULL,NULL,NULL }; \
 const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
 { return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
 
 #define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
 static const EVP_CIPHER aesni_##keylen##_##mode = { \
 	nid##_##keylen##_##mode,blocksize, \
 	(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aesni_##mode##_init_key,	\
 	aesni_##mode##_cipher,		\
 	aes_##mode##_cleanup,		\
 	sizeof(EVP_AES_##MODE##_CTX),	\
 	NULL,NULL,aes_##mode##_ctrl,NULL }; \
 static const EVP_CIPHER aes_##keylen##_##mode = { \
 	nid##_##keylen##_##mode,blocksize, \
 	(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aes_##mode##_init_key,		\
 	aes_##mode##_cipher,		\
 	aes_##mode##_cleanup,		\
 	sizeof(EVP_AES_##MODE##_CTX),	\
 	NULL,NULL,aes_##mode##_ctrl,NULL }; \
 const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
 { return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
 
 #else
 
 #define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
 static const EVP_CIPHER aes_##keylen##_##mode = { \
 	nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aes_init_key,			\
 	aes_##mode##_cipher,		\
 	NULL,				\
 	sizeof(EVP_AES_KEY),		\
 	NULL,NULL,NULL,NULL }; \
 const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
 { return &aes_##keylen##_##mode; }
 
 #define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
 static const EVP_CIPHER aes_##keylen##_##mode = { \
 	nid##_##keylen##_##mode,blocksize, \
 	(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
 	flags|EVP_CIPH_##MODE##_MODE,	\
 	aes_##mode##_init_key,		\
 	aes_##mode##_cipher,		\
 	aes_##mode##_cleanup,		\
 	sizeof(EVP_AES_##MODE##_CTX),	\
 	NULL,NULL,aes_##mode##_ctrl,NULL }; \
 const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
 { return &aes_##keylen##_##mode; }
 #endif
 
 #define BLOCK_CIPHER_generic_pack(nid,keylen,flags)		\
 	BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 	BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 	BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 	BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 	BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags)	\
 	BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)	\
 	BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags)
 
 static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 		   const unsigned char *iv, int enc)
 	{
 	int ret, mode;
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	mode = ctx->cipher->flags & EVP_CIPH_MODE;
 	if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
 	    && !enc)
 #ifdef BSAES_CAPABLE
 	    if (BSAES_CAPABLE && mode==EVP_CIPH_CBC_MODE)
 		{
 		ret = AES_set_decrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)AES_decrypt;
 		dat->stream.cbc	= (cbc128_f)bsaes_cbc_encrypt;
 		}
 	    else
 #endif
 #ifdef VPAES_CAPABLE
 	    if (VPAES_CAPABLE)
 		{
 		ret = vpaes_set_decrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)vpaes_decrypt;
 		dat->stream.cbc	= mode==EVP_CIPH_CBC_MODE ?
 					(cbc128_f)vpaes_cbc_encrypt :
 					NULL;
 		}
 	    else
 #endif
 		{
 		ret = AES_set_decrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)AES_decrypt;
 		dat->stream.cbc	= mode==EVP_CIPH_CBC_MODE ?
 					(cbc128_f)AES_cbc_encrypt :
 					NULL;
 		}
 	else
 #ifdef BSAES_CAPABLE
 	    if (BSAES_CAPABLE && mode==EVP_CIPH_CTR_MODE)
 		{
 		ret = AES_set_encrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)AES_encrypt;
 		dat->stream.ctr	= (ctr128_f)bsaes_ctr32_encrypt_blocks;
 		}
 	    else
 #endif
 #ifdef VPAES_CAPABLE
 	    if (VPAES_CAPABLE)
 		{
 		ret = vpaes_set_encrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)vpaes_encrypt;
 		dat->stream.cbc	= mode==EVP_CIPH_CBC_MODE ?
 					(cbc128_f)vpaes_cbc_encrypt :
 					NULL;
 		}
 	    else
 #endif
 		{
 		ret = AES_set_encrypt_key(key,ctx->key_len*8,&dat->ks);
 		dat->block	= (block128_f)AES_encrypt;
 		dat->stream.cbc	= mode==EVP_CIPH_CBC_MODE ?
 					(cbc128_f)AES_cbc_encrypt :
 					NULL;
 #ifdef AES_CTR_ASM
 		if (mode==EVP_CIPH_CTR_MODE)
 			dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
 #endif
 		}
 
 	if(ret < 0)
 		{
 		EVPerr(EVP_F_AES_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
 		return 0;
 		}
 
 	return 1;
 	}
 
 static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in, size_t len)
 {
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	if (dat->stream.cbc)
 		(*dat->stream.cbc)(in,out,len,&dat->ks,ctx->iv,ctx->encrypt);
 	else if (ctx->encrypt)
 		CRYPTO_cbc128_encrypt(in,out,len,&dat->ks,ctx->iv,dat->block);
 	else
 		CRYPTO_cbc128_encrypt(in,out,len,&dat->ks,ctx->iv,dat->block);
 
 	return 1;
 }
 
 static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in, size_t len)
 {
 	size_t	bl = ctx->cipher->block_size;
 	size_t	i;
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	if (lenblock)(in+i,out+i,&dat->ks);
 
 	return 1;
 }
 
 static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len)
 {
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	CRYPTO_ofb128_encrypt(in,out,len,&dat->ks,
 			ctx->iv,&ctx->num,dat->block);
 	return 1;
 }
 
 static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len)
 {
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	CRYPTO_cfb128_encrypt(in,out,len,&dat->ks,
 			ctx->iv,&ctx->num,ctx->encrypt,dat->block);
 	return 1;
 }
 
 static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len)
 {
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	CRYPTO_cfb128_8_encrypt(in,out,len,&dat->ks,
 			ctx->iv,&ctx->num,ctx->encrypt,dat->block);
 	return 1;
 }
 
 static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 	const unsigned char *in,size_t len)
 {
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	if (ctx->flags&EVP_CIPH_FLAG_LENGTH_BITS) {
 		CRYPTO_cfb128_1_encrypt(in,out,len,&dat->ks,
 			ctx->iv,&ctx->num,ctx->encrypt,dat->block);
 		return 1;
 	}
 
 	while (len>=MAXBITCHUNK) {
 		CRYPTO_cfb128_1_encrypt(in,out,MAXBITCHUNK*8,&dat->ks,
 			ctx->iv,&ctx->num,ctx->encrypt,dat->block);
 		len-=MAXBITCHUNK;
 	}
 	if (len)
 		CRYPTO_cfb128_1_encrypt(in,out,len*8,&dat->ks,
 			ctx->iv,&ctx->num,ctx->encrypt,dat->block);
 	
 	return 1;
 }
 
 static int aes_ctr_cipher (EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len)
 {
 	unsigned int num = ctx->num;
 	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
 	if (dat->stream.ctr)
 		CRYPTO_ctr128_encrypt_ctr32(in,out,len,&dat->ks,
 			ctx->iv,ctx->buf,&num,dat->stream.ctr);
 	else
 		CRYPTO_ctr128_encrypt(in,out,len,&dat->ks,
 			ctx->iv,ctx->buf,&num,dat->block);
 	ctx->num = (size_t)num;
 	return 1;
 }
 
 BLOCK_CIPHER_generic_pack(NID_aes,128,EVP_CIPH_FLAG_FIPS)
 BLOCK_CIPHER_generic_pack(NID_aes,192,EVP_CIPH_FLAG_FIPS)
 BLOCK_CIPHER_generic_pack(NID_aes,256,EVP_CIPH_FLAG_FIPS)
 
 static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
 	{
 	EVP_AES_GCM_CTX *gctx = c->cipher_data;
 	OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
 	if (gctx->iv != c->iv)
 		OPENSSL_free(gctx->iv);
 	return 1;
 	}
 
 /* increment counter (64-bit int) by 1 */
 static void ctr64_inc(unsigned char *counter) {
 	int n=8;
 	unsigned char  c;
 
 	do {
 		--n;
 		c = counter[n];
 		++c;
 		counter[n] = c;
 		if (c) return;
 	} while (n);
 }
 
 static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
 	{
 	EVP_AES_GCM_CTX *gctx = c->cipher_data;
 	switch (type)
 		{
 	case EVP_CTRL_INIT:
 		gctx->key_set = 0;
 		gctx->iv_set = 0;
 		gctx->ivlen = c->cipher->iv_len;
 		gctx->iv = c->iv;
 		gctx->taglen = -1;
 		gctx->iv_gen = 0;
 		gctx->tls_aad_len = -1;
 		return 1;
 
 	case EVP_CTRL_GCM_SET_IVLEN:
 		if (arg <= 0)
 			return 0;
 #ifdef OPENSSL_FIPS
 		if (FIPS_module_mode() && !(c->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)
 						 && arg < 12)
 			return 0;
 #endif
 		/* Allocate memory for IV if needed */
 		if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen))
 			{
 			if (gctx->iv != c->iv)
 				OPENSSL_free(gctx->iv);
 			gctx->iv = OPENSSL_malloc(arg);
 			if (!gctx->iv)
 				return 0;
 			}
 		gctx->ivlen = arg;
 		return 1;
 
 	case EVP_CTRL_GCM_SET_TAG:
 		if (arg <= 0 || arg > 16 || c->encrypt)
 			return 0;
 		memcpy(c->buf, ptr, arg);
 		gctx->taglen = arg;
 		return 1;
 
 	case EVP_CTRL_GCM_GET_TAG:
 		if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0)
 			return 0;
 		memcpy(ptr, c->buf, arg);
 		return 1;
 
 	case EVP_CTRL_GCM_SET_IV_FIXED:
 		/* Special case: -1 length restores whole IV */
 		if (arg == -1)
 			{
 			memcpy(gctx->iv, ptr, gctx->ivlen);
 			gctx->iv_gen = 1;
 			return 1;
 			}
 		/* Fixed field must be at least 4 bytes and invocation field
 		 * at least 8.
 		 */
 		if ((arg < 4) || (gctx->ivlen - arg) < 8)
 			return 0;
 		if (arg)
 			memcpy(gctx->iv, ptr, arg);
 		if (c->encrypt &&
 			RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
 			return 0;
 		gctx->iv_gen = 1;
 		return 1;
 
 	case EVP_CTRL_GCM_IV_GEN:
 		if (gctx->iv_gen == 0 || gctx->key_set == 0)
 			return 0;
 		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
 		if (arg <= 0 || arg > gctx->ivlen)
 			arg = gctx->ivlen;
 		memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
 		/* Invocation field will be at least 8 bytes in size and
 		 * so no need to check wrap around or increment more than
 		 * last 8 bytes.
 		 */
 		ctr64_inc(gctx->iv + gctx->ivlen - 8);
 		gctx->iv_set = 1;
 		return 1;
 
 	case EVP_CTRL_GCM_SET_IV_INV:
 		if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
 			return 0;
 		memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
 		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
 		gctx->iv_set = 1;
 		return 1;
 
 	case EVP_CTRL_AEAD_TLS1_AAD:
 		/* Save the AAD for later use */
 		if (arg != 13)
 			return 0;
 		memcpy(c->buf, ptr, arg);
 		gctx->tls_aad_len = arg;
 			{
 			unsigned int len=c->buf[arg-2]<<8|c->buf[arg-1];
 			/* Correct length for explicit IV */
 			len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
 			/* If decrypting correct for tag too */
 			if (!c->encrypt)
 				len -= EVP_GCM_TLS_TAG_LEN;
                         c->buf[arg-2] = len>>8;
                         c->buf[arg-1] = len & 0xff;
 			}
 		/* Extra padding: tag appended to record */
 		return EVP_GCM_TLS_TAG_LEN;
 
 	case EVP_CTRL_COPY:
 		{
 			EVP_CIPHER_CTX *out = ptr;
 			EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
 			if (gctx->gcm.key)
 				{
 				if (gctx->gcm.key != &gctx->ks)
 					return 0;
 				gctx_out->gcm.key = &gctx_out->ks;
 				}
 			if (gctx->iv == c->iv)
 				gctx_out->iv = out->iv;
 			else
 			{
 				gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
 				if (!gctx_out->iv)
 					return 0;
 				memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
 			}
 			return 1;
 		}
 
 	default:
 		return -1;
 
 		}
 	}
 
 static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 	if (key)
 		{ do {
 #ifdef BSAES_CAPABLE
 		if (BSAES_CAPABLE)
 			{
 			AES_set_encrypt_key(key,ctx->key_len*8,&gctx->ks);
 			CRYPTO_gcm128_init(&gctx->gcm,&gctx->ks,
 					(block128_f)AES_encrypt);
 			gctx->ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
 			break;
 			}
 		else
 #endif
 #ifdef VPAES_CAPABLE
 		if (VPAES_CAPABLE)
 			{
 			vpaes_set_encrypt_key(key,ctx->key_len*8,&gctx->ks);
 			CRYPTO_gcm128_init(&gctx->gcm,&gctx->ks,
 					(block128_f)vpaes_encrypt);
 			gctx->ctr = NULL;
 			break;
 			}
 		else
 #endif
 		(void)0;	/* terminate potentially open 'else' */
 
 		AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
 		CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)AES_encrypt);
 #ifdef AES_CTR_ASM
 		gctx->ctr = (ctr128_f)AES_ctr32_encrypt;
 #else
 		gctx->ctr = NULL;
 #endif
 		} while (0);
 
 		/* If we have an iv can set it directly, otherwise use
 		 * saved IV.
 		 */
 		if (iv == NULL && gctx->iv_set)
 			iv = gctx->iv;
 		if (iv)
 			{
 			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
 			gctx->iv_set = 1;
 			}
 		gctx->key_set = 1;
 		}
 	else
 		{
 		/* If key set use IV, otherwise copy */
 		if (gctx->key_set)
 			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
 		else
 			memcpy(gctx->iv, iv, gctx->ivlen);
 		gctx->iv_set = 1;
 		gctx->iv_gen = 0;
 		}
 	return 1;
 	}
 
 /* Handle TLS GCM packet format. This consists of the last portion of the IV
  * followed by the payload and finally the tag. On encrypt generate IV,
  * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
  * and verify tag.
  */
 
 static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len)
 	{
 	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
 	int rv = -1;
 	/* Encrypt/decrypt must be performed in place */
 	if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN+EVP_GCM_TLS_TAG_LEN))
 		return -1;
 	/* Set IV from start of buffer or generate IV and write to start
 	 * of buffer.
 	 */
 	if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
 				EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
 				EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
 		goto err;
 	/* Use saved AAD */
 	if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
 		goto err;
 	/* Fix buffer and length to point to payload */
 	in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 	out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
 	if (ctx->encrypt)
 		{
 		/* Encrypt payload */
 		if (gctx->ctr)
 			{
 			if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
 							in, out, len,
 							gctx->ctr))
 				goto err;
 			}
 		else	{
 			if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
 				goto err;
 			}
 		out += len;
 		/* Finally write tag */
 		CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
 		rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
 		}
 	else
 		{
 		/* Decrypt */
 		if (gctx->ctr)
 			{
 			if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
 							in, out, len,
 							gctx->ctr))
 				goto err;
 			}
 		else	{
 			if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
 				goto err;
 			}
 		/* Retrieve tag */
 		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf,
 					EVP_GCM_TLS_TAG_LEN);
 		/* If tag mismatch wipe buffer */
-		if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN))
+		if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN))
 			{
 			OPENSSL_cleanse(out, len);
 			goto err;
 			}
 		rv = len;
 		}
 
 	err:
 	gctx->iv_set = 0;
 	gctx->tls_aad_len = -1;
 	return rv;
 	}
 
 static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len)
 	{
 	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
 	/* If not set up, return error */
 	if (!gctx->key_set)
 		return -1;
 
 	if (gctx->tls_aad_len >= 0)
 		return aes_gcm_tls_cipher(ctx, out, in, len);
 
 	if (!gctx->iv_set)
 		return -1;
 	if (in)
 		{
 		if (out == NULL)
 			{
 			if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
 				return -1;
 			}
 		else if (ctx->encrypt)
 			{
 			if (gctx->ctr)
 				{
 				if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
 							in, out, len,
 							gctx->ctr))
 					return -1;
 				}
 			else	{
 				if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
 					return -1;
 				}
 			}
 		else
 			{
 			if (gctx->ctr)
 				{
 				if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
 							in, out, len,
 							gctx->ctr))
 					return -1;
 				}
 			else	{
 				if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
 					return -1;
 				}
 			}
 		return len;
 		}
 	else
 		{
 		if (!ctx->encrypt)
 			{
 			if (gctx->taglen < 0)
 				return -1;
 			if (CRYPTO_gcm128_finish(&gctx->gcm,
 					ctx->buf, gctx->taglen) != 0)
 				return -1;
 			gctx->iv_set = 0;
 			return 0;
 			}
 		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
 		gctx->taglen = 16;
 		/* Don't reuse the IV */
 		gctx->iv_set = 0;
 		return 0;
 		}
 
 	}
 
 #define CUSTOM_FLAGS	(EVP_CIPH_FLAG_DEFAULT_ASN1 \
 		| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
 		| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
 		| EVP_CIPH_CUSTOM_COPY)
 
 BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,
 		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,192,1,12,gcm,GCM,
 		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,
 		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
 
 static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
 	{
 	EVP_AES_XTS_CTX *xctx = c->cipher_data;
 	if (type == EVP_CTRL_COPY)
 		{
 		EVP_CIPHER_CTX *out = ptr;
 		EVP_AES_XTS_CTX *xctx_out = out->cipher_data;
 		if (xctx->xts.key1)
 			{
 			if (xctx->xts.key1 != &xctx->ks1)
 				return 0;
 			xctx_out->xts.key1 = &xctx_out->ks1;
 			}
 		if (xctx->xts.key2)
 			{
 			if (xctx->xts.key2 != &xctx->ks2)
 				return 0;
 			xctx_out->xts.key2 = &xctx_out->ks2;
 			}
 		return 1;
 		}
 	else if (type != EVP_CTRL_INIT)
 		return -1;
 	/* key1 and key2 are used as an indicator both key and IV are set */
 	xctx->xts.key1 = NULL;
 	xctx->xts.key2 = NULL;
 	return 1;
 	}
 
 static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 
 	if (key) do
 		{
 #ifdef AES_XTS_ASM
 		xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
 #else
 		xctx->stream = NULL;
 #endif
 		/* key_len is two AES keys */
 #ifdef BSAES_CAPABLE
 		if (BSAES_CAPABLE)
 			xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt;
 		else
 #endif
 #ifdef VPAES_CAPABLE
 		if (VPAES_CAPABLE)
 		    {
 		    if (enc)
 			{
 			vpaes_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)vpaes_encrypt;
 			}
 		    else
 			{
 			vpaes_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)vpaes_decrypt;
 			}
 
 		    vpaes_set_encrypt_key(key + ctx->key_len/2,
 						ctx->key_len * 4, &xctx->ks2);
 		    xctx->xts.block2 = (block128_f)vpaes_encrypt;
 
 		    xctx->xts.key1 = &xctx->ks1;
 		    break;
 		    }
 		else
 #endif
 		(void)0;	/* terminate potentially open 'else' */
 
 		if (enc)
 			{
 			AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)AES_encrypt;
 			}
 		else
 			{
 			AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 			xctx->xts.block1 = (block128_f)AES_decrypt;
 			}
 
 		AES_set_encrypt_key(key + ctx->key_len/2,
 						ctx->key_len * 4, &xctx->ks2);
 		xctx->xts.block2 = (block128_f)AES_encrypt;
 
 		xctx->xts.key1 = &xctx->ks1;
 		} while (0);
 
 	if (iv)
 		{
 		xctx->xts.key2 = &xctx->ks2;
 		memcpy(ctx->iv, iv, 16);
 		}
 
 	return 1;
 	}
 
 static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len)
 	{
 	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
 	if (!xctx->xts.key1 || !xctx->xts.key2)
 		return 0;
 	if (!out || !in || lenflags & EVP_CIPH_FLAG_NON_FIPS_ALLOW) &&
 			(len > (1UL<<20)*16))
 		{
 		EVPerr(EVP_F_AES_XTS_CIPHER, EVP_R_TOO_LARGE);
 		return 0;
 		}
 #endif
 	if (xctx->stream)
 		(*xctx->stream)(in, out, len,
 				xctx->xts.key1, xctx->xts.key2, ctx->iv);
 	else if (CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len,
 								ctx->encrypt))
 		return 0;
 	return 1;
 	}
 
 #define aes_xts_cleanup NULL
 
 #define XTS_FLAGS	(EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
 			 | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
 			 | EVP_CIPH_CUSTOM_COPY)
 
 BLOCK_CIPHER_custom(NID_aes,128,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,256,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
 
 static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
 	{
 	EVP_AES_CCM_CTX *cctx = c->cipher_data;
 	switch (type)
 		{
 	case EVP_CTRL_INIT:
 		cctx->key_set = 0;
 		cctx->iv_set = 0;
 		cctx->L = 8;
 		cctx->M = 12;
 		cctx->tag_set = 0;
 		cctx->len_set = 0;
 		return 1;
 
 	case EVP_CTRL_CCM_SET_IVLEN:
 		arg = 15 - arg;
 	case EVP_CTRL_CCM_SET_L:
 		if (arg < 2 || arg > 8)
 			return 0;
 		cctx->L = arg;
 		return 1;
 
 	case EVP_CTRL_CCM_SET_TAG:
 		if ((arg & 1) || arg < 4 || arg > 16)
 			return 0;
 		if ((c->encrypt && ptr) || (!c->encrypt && !ptr))
 			return 0;
 		if (ptr)
 			{
 			cctx->tag_set = 1;
 			memcpy(c->buf, ptr, arg);
 			}
 		cctx->M = arg;
 		return 1;
 
 	case EVP_CTRL_CCM_GET_TAG:
 		if (!c->encrypt || !cctx->tag_set)
 			return 0;
 		if(!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
 			return 0;
 		cctx->tag_set = 0;
 		cctx->iv_set = 0;
 		cctx->len_set = 0;
 		return 1;
 
 	case EVP_CTRL_COPY:
 		{
 			EVP_CIPHER_CTX *out = ptr;
 			EVP_AES_CCM_CTX *cctx_out = out->cipher_data;
 			if (cctx->ccm.key)
 				{
 				if (cctx->ccm.key != &cctx->ks)
 					return 0;
 				cctx_out->ccm.key = &cctx_out->ks;
 				}
 			return 1;
 		}
 
 	default:
 		return -1;
 
 		}
 	}
 
 static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                         const unsigned char *iv, int enc)
 	{
 	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
 	if (!iv && !key)
 		return 1;
 	if (key) do
 		{
 #ifdef VPAES_CAPABLE
 		if (VPAES_CAPABLE)
 			{
 			vpaes_set_encrypt_key(key, ctx->key_len*8, &cctx->ks);
 			CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
 					&cctx->ks, (block128_f)vpaes_encrypt);
 			cctx->str = NULL;
 			cctx->key_set = 1;
 			break;
 			}
 #endif
 		AES_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
 		CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
 					&cctx->ks, (block128_f)AES_encrypt);
 		cctx->str = NULL;
 		cctx->key_set = 1;
 		} while (0);
 	if (iv)
 		{
 		memcpy(ctx->iv, iv, 15 - cctx->L);
 		cctx->iv_set = 1;
 		}
 	return 1;
 	}
 
 static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		const unsigned char *in, size_t len)
 	{
 	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
 	CCM128_CONTEXT *ccm = &cctx->ccm;
 	/* If not set up, return error */
 	if (!cctx->iv_set && !cctx->key_set)
 		return -1;
 	if (!ctx->encrypt && !cctx->tag_set)
 		return -1;
 	if (!out)
 		{
 		if (!in)
 			{
 			if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,len))
 				return -1;
 			cctx->len_set = 1;
 			return len;
 			}
 		/* If have AAD need message length */
 		if (!cctx->len_set && len)
 			return -1;
 		CRYPTO_ccm128_aad(ccm, in, len);
 		return len;
 		}
 	/* EVP_*Final() doesn't return any data */
 	if (!in)
 		return 0;
 	/* If not set length yet do it */
 	if (!cctx->len_set)
 		{
 		if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
 			return -1;
 		cctx->len_set = 1;
 		}
 	if (ctx->encrypt)
 		{
 		if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
 						cctx->str) :
 				CRYPTO_ccm128_encrypt(ccm, in, out, len))
 			return -1;
 		cctx->tag_set = 1;
 		return len;
 		}
 	else
 		{
 		int rv = -1;
 		if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
 						cctx->str) :
 				!CRYPTO_ccm128_decrypt(ccm, in, out, len))
 			{
 			unsigned char tag[16];
 			if (CRYPTO_ccm128_tag(ccm, tag, cctx->M))
 				{
-				if (!memcmp(tag, ctx->buf, cctx->M))
+				if (!CRYPTO_memcmp(tag, ctx->buf, cctx->M))
 					rv = len;
 				}
 			}
 		if (rv == -1)
 			OPENSSL_cleanse(out, len);
 		cctx->iv_set = 0;
 		cctx->tag_set = 0;
 		cctx->len_set = 0;
 		return rv;
 		}
 
 	}
 
 #define aes_ccm_cleanup NULL
 
 BLOCK_CIPHER_custom(NID_aes,128,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,192,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,256,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
 
 #endif
 #endif
Index: releng/10.1/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c	(revision 284295)
@@ -1,298 +1,299 @@
 /* ====================================================================
  * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  */
 
 #include 
 
 #include 
 #include 
 
 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5)
 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 #ifndef EVP_CIPH_FLAG_AEAD_CIPHER
 #define EVP_CIPH_FLAG_AEAD_CIPHER	0x200000
 #define EVP_CTRL_AEAD_TLS1_AAD		0x16
 #define EVP_CTRL_AEAD_SET_MAC_KEY	0x17
 #endif
 
 /* FIXME: surely this is available elsewhere? */
 #define EVP_RC4_KEY_SIZE		16
 
 typedef struct
     {
     RC4_KEY		ks;
     MD5_CTX		head,tail,md;
     size_t		payload_length;
     } EVP_RC4_HMAC_MD5;
 
 #define NO_PAYLOAD_LENGTH	((size_t)-1)
 
 void rc4_md5_enc (RC4_KEY *key, const void *in0, void *out,
 		MD5_CTX *ctx,const void *inp,size_t blocks);
 
 #define data(ctx) ((EVP_RC4_HMAC_MD5 *)(ctx)->cipher_data)
 
 static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
 			const unsigned char *inkey,
 			const unsigned char *iv, int enc)
 	{
 	EVP_RC4_HMAC_MD5 *key = data(ctx);
 
 	RC4_set_key(&key->ks,EVP_CIPHER_CTX_key_length(ctx),
 		    inkey);
 
 	MD5_Init(&key->head);	/* handy when benchmarking */
 	key->tail = key->head;
 	key->md   = key->head;
 
 	key->payload_length = NO_PAYLOAD_LENGTH;
 
 	return 1;
 	}
 
 #if	!defined(OPENSSL_NO_ASM) &&	( \
 	defined(__x86_64)	|| defined(__x86_64__)	|| \
 	defined(_M_AMD64)	|| defined(_M_X64)	|| \
 	defined(__INTEL__)		) && \
 	!(defined(__APPLE__) && defined(__MACH__))
 #define	STITCHED_CALL
 #endif
 
 #if !defined(STITCHED_CALL)
 #define	rc4_off 0
 #define	md5_off 0
 #endif
 
 static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		      const unsigned char *in, size_t len)
 	{
 	EVP_RC4_HMAC_MD5 *key = data(ctx);
 #if defined(STITCHED_CALL)
 	size_t	rc4_off = 32-1-(key->ks.x&(32-1)),	/* 32 is $MOD from rc4_md5-x86_64.pl */
 		md5_off = MD5_CBLOCK-key->md.num,
 		blocks;
 	unsigned int l;
 	extern unsigned int OPENSSL_ia32cap_P[];
 #endif
 	size_t	plen = key->payload_length;
 
 	if (plen!=NO_PAYLOAD_LENGTH && len!=(plen+MD5_DIGEST_LENGTH)) return 0;
 
 	if (ctx->encrypt) {
 		if (plen==NO_PAYLOAD_LENGTH) plen = len;
 #if defined(STITCHED_CALL)
 		/* cipher has to "fall behind" */
 		if (rc4_off>md5_off) md5_off+=MD5_CBLOCK;
 
 		if (plen>md5_off && (blocks=(plen-md5_off)/MD5_CBLOCK) &&
 		    (OPENSSL_ia32cap_P[0]&(1<<20))==0) {
 			MD5_Update(&key->md,in,md5_off);
 			RC4(&key->ks,rc4_off,in,out);
 
 			rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off,
 				&key->md,in+md5_off,blocks);
 			blocks *= MD5_CBLOCK;
 			rc4_off += blocks;
 			md5_off += blocks;
 			key->md.Nh += blocks>>29;
 			key->md.Nl += blocks<<=3;
 			if (key->md.Nl<(unsigned int)blocks) key->md.Nh++;
 		} else {
 			rc4_off = 0;
 			md5_off = 0;
 		}
 #endif
 		MD5_Update(&key->md,in+md5_off,plen-md5_off);
 
 		if (plen!=len) {	/* "TLS" mode of operation */
 			if (in!=out)
 				memcpy(out+rc4_off,in+rc4_off,plen-rc4_off);
 
 			/* calculate HMAC and append it to payload */
 			MD5_Final(out+plen,&key->md);
 			key->md = key->tail;
 			MD5_Update(&key->md,out+plen,MD5_DIGEST_LENGTH);
 			MD5_Final(out+plen,&key->md);
 			/* encrypt HMAC at once */
 			RC4(&key->ks,len-rc4_off,out+rc4_off,out+rc4_off);
 		} else {
 			RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off);
 		}
 	} else {
 		unsigned char mac[MD5_DIGEST_LENGTH];
 #if defined(STITCHED_CALL)
 		/* digest has to "fall behind" */
 		if (md5_off>rc4_off)	rc4_off += 2*MD5_CBLOCK;
 		else			rc4_off += MD5_CBLOCK;
 
 		if (len>rc4_off && (blocks=(len-rc4_off)/MD5_CBLOCK) &&
 		    (OPENSSL_ia32cap_P[0]&(1<<20))==0) {
 			RC4(&key->ks,rc4_off,in,out);
 			MD5_Update(&key->md,out,md5_off);
 
 			rc4_md5_enc(&key->ks,in+rc4_off,out+rc4_off,
 				&key->md,out+md5_off,blocks);
 			blocks *= MD5_CBLOCK;
 			rc4_off += blocks;
 			md5_off += blocks;
 			l = (key->md.Nl+(blocks<<3))&0xffffffffU;
 			if (lmd.Nl) key->md.Nh++;
 			key->md.Nl  = l;
 			key->md.Nh += blocks>>29;
 		} else {
 			md5_off=0;
 			rc4_off=0;
 		}
 #endif
 		/* decrypt HMAC at once */
 		RC4(&key->ks,len-rc4_off,in+rc4_off,out+rc4_off);
 		if (plen!=NO_PAYLOAD_LENGTH) {	/* "TLS" mode of operation */
 			MD5_Update(&key->md,out+md5_off,plen-md5_off);
 
 			/* calculate HMAC and verify it */
 			MD5_Final(mac,&key->md);
 			key->md = key->tail;
 			MD5_Update(&key->md,mac,MD5_DIGEST_LENGTH);
 			MD5_Final(mac,&key->md);
 
-			if (memcmp(out+plen,mac,MD5_DIGEST_LENGTH))
+			if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH))
 				return 0;
 		} else {
 			MD5_Update(&key->md,out+md5_off,len-md5_off);
 		}
 	}
 
 	key->payload_length = NO_PAYLOAD_LENGTH;
 
 	return 1;
 	}
 
 static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 	{
 	EVP_RC4_HMAC_MD5 *key = data(ctx);
 
 	switch (type)
 		{
 	case EVP_CTRL_AEAD_SET_MAC_KEY:
 		{
 		unsigned int  i;
 		unsigned char hmac_key[64];
 
 		memset (hmac_key,0,sizeof(hmac_key));
 
 		if (arg > (int)sizeof(hmac_key)) {
 			MD5_Init(&key->head);
 			MD5_Update(&key->head,ptr,arg);
 			MD5_Final(hmac_key,&key->head);
 		} else {
 			memcpy(hmac_key,ptr,arg);
 		}
 
 		for (i=0;ihead);
 		MD5_Update(&key->head,hmac_key,sizeof(hmac_key));
 
 		for (i=0;itail);
 		MD5_Update(&key->tail,hmac_key,sizeof(hmac_key));
 
 		return 1;
 		}
 	case EVP_CTRL_AEAD_TLS1_AAD:
 		{
 		unsigned char *p=ptr;
 		unsigned int   len=p[arg-2]<<8|p[arg-1];
 
 		if (!ctx->encrypt)
 			{
 			len -= MD5_DIGEST_LENGTH;
 			p[arg-2] = len>>8;
 			p[arg-1] = len;
 			}
 		key->payload_length=len;
 		key->md = key->head;
 		MD5_Update(&key->md,p,arg);
 
 		return MD5_DIGEST_LENGTH;
 		}
 	default:
 		return -1;
 		}
 	}
 
 static EVP_CIPHER r4_hmac_md5_cipher=
 	{
 #ifdef NID_rc4_hmac_md5
 	NID_rc4_hmac_md5,
 #else
 	NID_undef,
 #endif
 	1,EVP_RC4_KEY_SIZE,0,
 	EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_FLAG_AEAD_CIPHER,
 	rc4_hmac_md5_init_key,
 	rc4_hmac_md5_cipher,
 	NULL,
 	sizeof(EVP_RC4_HMAC_MD5),
 	NULL,
 	NULL,
 	rc4_hmac_md5_ctrl,
 	NULL
 	};
 
 const EVP_CIPHER *EVP_rc4_hmac_md5(void)
 	{
 	return(&r4_hmac_md5_cipher);
 	}
 #endif
Index: releng/10.1/crypto/openssl/crypto/evp/evp.h
===================================================================
--- releng/10.1/crypto/openssl/crypto/evp/evp.h	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/evp/evp.h	(revision 284295)
@@ -1,1409 +1,1408 @@
 /* crypto/evp/evp.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #ifndef HEADER_ENVELOPE_H
 #define HEADER_ENVELOPE_H
 
 #ifdef OPENSSL_ALGORITHM_DEFINES
 # include 
 #else
 # define OPENSSL_ALGORITHM_DEFINES
 # include 
 # undef OPENSSL_ALGORITHM_DEFINES
 #endif
 
 #include 
 
 #include 
 
 #ifndef OPENSSL_NO_BIO
 #include 
 #endif
 
 /*
 #define EVP_RC2_KEY_SIZE		16
 #define EVP_RC4_KEY_SIZE		16
 #define EVP_BLOWFISH_KEY_SIZE		16
 #define EVP_CAST5_KEY_SIZE		16
 #define EVP_RC5_32_12_16_KEY_SIZE	16
 */
 #define EVP_MAX_MD_SIZE			64	/* longest known is SHA512 */
 #define EVP_MAX_KEY_LENGTH		64
 #define EVP_MAX_IV_LENGTH		16
 #define EVP_MAX_BLOCK_LENGTH		32
 
 #define PKCS5_SALT_LEN			8
 /* Default PKCS#5 iteration count */
 #define PKCS5_DEFAULT_ITER		2048
 
 #include 
 
 #define EVP_PK_RSA	0x0001
 #define EVP_PK_DSA	0x0002
 #define EVP_PK_DH	0x0004
 #define EVP_PK_EC	0x0008
 #define EVP_PKT_SIGN	0x0010
 #define EVP_PKT_ENC	0x0020
 #define EVP_PKT_EXCH	0x0040
 #define EVP_PKS_RSA	0x0100
 #define EVP_PKS_DSA	0x0200
 #define EVP_PKS_EC	0x0400
-#define EVP_PKT_EXP	0x1000 /* <= 512 bit key */
 
 #define EVP_PKEY_NONE	NID_undef
 #define EVP_PKEY_RSA	NID_rsaEncryption
 #define EVP_PKEY_RSA2	NID_rsa
 #define EVP_PKEY_DSA	NID_dsa
 #define EVP_PKEY_DSA1	NID_dsa_2
 #define EVP_PKEY_DSA2	NID_dsaWithSHA
 #define EVP_PKEY_DSA3	NID_dsaWithSHA1
 #define EVP_PKEY_DSA4	NID_dsaWithSHA1_2
 #define EVP_PKEY_DH	NID_dhKeyAgreement
 #define EVP_PKEY_EC	NID_X9_62_id_ecPublicKey
 #define EVP_PKEY_HMAC	NID_hmac
 #define EVP_PKEY_CMAC	NID_cmac
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 /* Type needs to be a bit field
  * Sub-type needs to be for variations on the method, as in, can it do
  * arbitrary encryption.... */
 struct evp_pkey_st
 	{
 	int type;
 	int save_type;
 	int references;
 	const EVP_PKEY_ASN1_METHOD *ameth;
 	ENGINE *engine;
 	union	{
 		char *ptr;
 #ifndef OPENSSL_NO_RSA
 		struct rsa_st *rsa;	/* RSA */
 #endif
 #ifndef OPENSSL_NO_DSA
 		struct dsa_st *dsa;	/* DSA */
 #endif
 #ifndef OPENSSL_NO_DH
 		struct dh_st *dh;	/* DH */
 #endif
 #ifndef OPENSSL_NO_EC
 		struct ec_key_st *ec;	/* ECC */
 #endif
 		} pkey;
 	int save_parameters;
 	STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
 	} /* EVP_PKEY */;
 
 #define EVP_PKEY_MO_SIGN	0x0001
 #define EVP_PKEY_MO_VERIFY	0x0002
 #define EVP_PKEY_MO_ENCRYPT	0x0004
 #define EVP_PKEY_MO_DECRYPT	0x0008
 
 #ifndef EVP_MD
 struct env_md_st
 	{
 	int type;
 	int pkey_type;
 	int md_size;
 	unsigned long flags;
 	int (*init)(EVP_MD_CTX *ctx);
 	int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
 	int (*final)(EVP_MD_CTX *ctx,unsigned char *md);
 	int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);
 	int (*cleanup)(EVP_MD_CTX *ctx);
 
 	/* FIXME: prototype these some day */
 	int (*sign)(int type, const unsigned char *m, unsigned int m_length,
 		    unsigned char *sigret, unsigned int *siglen, void *key);
 	int (*verify)(int type, const unsigned char *m, unsigned int m_length,
 		      const unsigned char *sigbuf, unsigned int siglen,
 		      void *key);
 	int required_pkey_type[5]; /*EVP_PKEY_xxx */
 	int block_size;
 	int ctx_size; /* how big does the ctx->md_data need to be */
 	/* control function */
 	int (*md_ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
 	} /* EVP_MD */;
 
 typedef int evp_sign_method(int type,const unsigned char *m,
 			    unsigned int m_length,unsigned char *sigret,
 			    unsigned int *siglen, void *key);
 typedef int evp_verify_method(int type,const unsigned char *m,
 			    unsigned int m_length,const unsigned char *sigbuf,
 			    unsigned int siglen, void *key);
 
 #define EVP_MD_FLAG_ONESHOT	0x0001 /* digest can only handle a single
 					* block */
 
 #define EVP_MD_FLAG_PKEY_DIGEST	0x0002 /* digest is a "clone" digest used
 					* which is a copy of an existing
 					* one for a specific public key type.
 					* EVP_dss1() etc */
 
 /* Digest uses EVP_PKEY_METHOD for signing instead of MD specific signing */
 
 #define EVP_MD_FLAG_PKEY_METHOD_SIGNATURE	0x0004
 
 /* DigestAlgorithmIdentifier flags... */
 
 #define EVP_MD_FLAG_DIGALGID_MASK		0x0018
 
 /* NULL or absent parameter accepted. Use NULL */
 
 #define EVP_MD_FLAG_DIGALGID_NULL		0x0000
 
 /* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */
 
 #define EVP_MD_FLAG_DIGALGID_ABSENT		0x0008
 
 /* Custom handling via ctrl */
 
 #define EVP_MD_FLAG_DIGALGID_CUSTOM		0x0018
 
 #define EVP_MD_FLAG_FIPS	0x0400 /* Note if suitable for use in FIPS mode */
 
 /* Digest ctrls */
 
 #define	EVP_MD_CTRL_DIGALGID			0x1
 #define	EVP_MD_CTRL_MICALG			0x2
 
 /* Minimum Algorithm specific ctrl value */
 
 #define	EVP_MD_CTRL_ALG_CTRL			0x1000
 
 #define EVP_PKEY_NULL_method	NULL,NULL,{0,0,0,0}
 
 #ifndef OPENSSL_NO_DSA
 #define EVP_PKEY_DSA_method	(evp_sign_method *)DSA_sign, \
 				(evp_verify_method *)DSA_verify, \
 				{EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \
 					EVP_PKEY_DSA4,0}
 #else
 #define EVP_PKEY_DSA_method	EVP_PKEY_NULL_method
 #endif
 
 #ifndef OPENSSL_NO_ECDSA
 #define EVP_PKEY_ECDSA_method   (evp_sign_method *)ECDSA_sign, \
 				(evp_verify_method *)ECDSA_verify, \
                                  {EVP_PKEY_EC,0,0,0}
 #else   
 #define EVP_PKEY_ECDSA_method   EVP_PKEY_NULL_method
 #endif
 
 #ifndef OPENSSL_NO_RSA
 #define EVP_PKEY_RSA_method	(evp_sign_method *)RSA_sign, \
 				(evp_verify_method *)RSA_verify, \
 				{EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
 #define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \
 				(evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \
 				(evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \
 				{EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
 #else
 #define EVP_PKEY_RSA_method	EVP_PKEY_NULL_method
 #define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method
 #endif
 
 #endif /* !EVP_MD */
 
 struct env_md_ctx_st
 	{
 	const EVP_MD *digest;
 	ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */
 	unsigned long flags;
 	void *md_data;
 	/* Public key context for sign/verify */
 	EVP_PKEY_CTX *pctx;
 	/* Update function: usually copied from EVP_MD */
 	int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
 	} /* EVP_MD_CTX */;
 
 /* values for EVP_MD_CTX flags */
 
 #define EVP_MD_CTX_FLAG_ONESHOT		0x0001 /* digest update will be called
 						* once only */
 #define EVP_MD_CTX_FLAG_CLEANED		0x0002 /* context has already been
 						* cleaned */
 #define EVP_MD_CTX_FLAG_REUSE		0x0004 /* Don't free up ctx->md_data
 						* in EVP_MD_CTX_cleanup */
 /* FIPS and pad options are ignored in 1.0.0, definitions are here
  * so we don't accidentally reuse the values for other purposes.
  */
 
 #define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW	0x0008	/* Allow use of non FIPS digest
 						 * in FIPS mode */
 
 /* The following PAD options are also currently ignored in 1.0.0, digest
  * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*()
  * instead.
  */
 #define EVP_MD_CTX_FLAG_PAD_MASK	0xF0	/* RSA mode to use */
 #define EVP_MD_CTX_FLAG_PAD_PKCS1	0x00	/* PKCS#1 v1.5 mode */
 #define EVP_MD_CTX_FLAG_PAD_X931	0x10	/* X9.31 mode */
 #define EVP_MD_CTX_FLAG_PAD_PSS		0x20	/* PSS mode */
 
 #define EVP_MD_CTX_FLAG_NO_INIT		0x0100 /* Don't initialize md_data */
 
 struct evp_cipher_st
 	{
 	int nid;
 	int block_size;
 	int key_len;		/* Default value for variable length ciphers */
 	int iv_len;
 	unsigned long flags;	/* Various flags */
 	int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 		    const unsigned char *iv, int enc);	/* init key */
 	int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
 			 const unsigned char *in, size_t inl);/* encrypt/decrypt data */
 	int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */
 	int ctx_size;		/* how big ctx->cipher_data needs to be */
 	int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */
 	int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */
 	int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */
 	void *app_data;		/* Application data */
 	} /* EVP_CIPHER */;
 
 /* Values for cipher flags */
 
 /* Modes for ciphers */
 
 #define		EVP_CIPH_STREAM_CIPHER		0x0
 #define		EVP_CIPH_ECB_MODE		0x1
 #define		EVP_CIPH_CBC_MODE		0x2
 #define		EVP_CIPH_CFB_MODE		0x3
 #define		EVP_CIPH_OFB_MODE		0x4
 #define		EVP_CIPH_CTR_MODE		0x5
 #define		EVP_CIPH_GCM_MODE		0x6
 #define		EVP_CIPH_CCM_MODE		0x7
 #define		EVP_CIPH_XTS_MODE		0x10001
 #define 	EVP_CIPH_MODE			0xF0007
 /* Set if variable length cipher */
 #define 	EVP_CIPH_VARIABLE_LENGTH	0x8
 /* Set if the iv handling should be done by the cipher itself */
 #define 	EVP_CIPH_CUSTOM_IV		0x10
 /* Set if the cipher's init() function should be called if key is NULL */
 #define 	EVP_CIPH_ALWAYS_CALL_INIT	0x20
 /* Call ctrl() to init cipher parameters */
 #define 	EVP_CIPH_CTRL_INIT		0x40
 /* Don't use standard key length function */
 #define 	EVP_CIPH_CUSTOM_KEY_LENGTH	0x80
 /* Don't use standard block padding */
 #define 	EVP_CIPH_NO_PADDING		0x100
 /* cipher handles random key generation */
 #define 	EVP_CIPH_RAND_KEY		0x200
 /* cipher has its own additional copying logic */
 #define 	EVP_CIPH_CUSTOM_COPY		0x400
 /* Allow use default ASN1 get/set iv */
 #define		EVP_CIPH_FLAG_DEFAULT_ASN1	0x1000
 /* Buffer length in bits not bytes: CFB1 mode only */
 #define		EVP_CIPH_FLAG_LENGTH_BITS	0x2000
 /* Note if suitable for use in FIPS mode */
 #define		EVP_CIPH_FLAG_FIPS		0x4000
 /* Allow non FIPS cipher in FIPS mode */
 #define		EVP_CIPH_FLAG_NON_FIPS_ALLOW	0x8000
 /* Cipher handles any and all padding logic as well
  * as finalisation.
  */
 #define 	EVP_CIPH_FLAG_CUSTOM_CIPHER	0x100000
 #define		EVP_CIPH_FLAG_AEAD_CIPHER	0x200000
 
 /* ctrl() values */
 
 #define		EVP_CTRL_INIT			0x0
 #define 	EVP_CTRL_SET_KEY_LENGTH		0x1
 #define 	EVP_CTRL_GET_RC2_KEY_BITS	0x2
 #define 	EVP_CTRL_SET_RC2_KEY_BITS	0x3
 #define 	EVP_CTRL_GET_RC5_ROUNDS		0x4
 #define 	EVP_CTRL_SET_RC5_ROUNDS		0x5
 #define 	EVP_CTRL_RAND_KEY		0x6
 #define 	EVP_CTRL_PBE_PRF_NID		0x7
 #define 	EVP_CTRL_COPY			0x8
 #define 	EVP_CTRL_GCM_SET_IVLEN		0x9
 #define 	EVP_CTRL_GCM_GET_TAG		0x10
 #define 	EVP_CTRL_GCM_SET_TAG		0x11
 #define		EVP_CTRL_GCM_SET_IV_FIXED	0x12
 #define		EVP_CTRL_GCM_IV_GEN		0x13
 #define		EVP_CTRL_CCM_SET_IVLEN		EVP_CTRL_GCM_SET_IVLEN
 #define		EVP_CTRL_CCM_GET_TAG		EVP_CTRL_GCM_GET_TAG
 #define		EVP_CTRL_CCM_SET_TAG		EVP_CTRL_GCM_SET_TAG
 #define		EVP_CTRL_CCM_SET_L		0x14
 #define		EVP_CTRL_CCM_SET_MSGLEN		0x15
 /* AEAD cipher deduces payload length and returns number of bytes
  * required to store MAC and eventual padding. Subsequent call to
  * EVP_Cipher even appends/verifies MAC.
  */
 #define		EVP_CTRL_AEAD_TLS1_AAD		0x16
 /* Used by composite AEAD ciphers, no-op in GCM, CCM... */
 #define		EVP_CTRL_AEAD_SET_MAC_KEY	0x17
 /* Set the GCM invocation field, decrypt only */
 #define		EVP_CTRL_GCM_SET_IV_INV		0x18
 
 /* GCM TLS constants */
 /* Length of fixed part of IV derived from PRF */
 #define EVP_GCM_TLS_FIXED_IV_LEN			4
 /* Length of explicit part of IV part of TLS records */
 #define EVP_GCM_TLS_EXPLICIT_IV_LEN			8
 /* Length of tag for TLS */
 #define EVP_GCM_TLS_TAG_LEN				16
 
 typedef struct evp_cipher_info_st
 	{
 	const EVP_CIPHER *cipher;
 	unsigned char iv[EVP_MAX_IV_LENGTH];
 	} EVP_CIPHER_INFO;
 
 struct evp_cipher_ctx_st
 	{
 	const EVP_CIPHER *cipher;
 	ENGINE *engine;	/* functional reference if 'cipher' is ENGINE-provided */
 	int encrypt;		/* encrypt or decrypt */
 	int buf_len;		/* number we have left */
 
 	unsigned char  oiv[EVP_MAX_IV_LENGTH];	/* original iv */
 	unsigned char  iv[EVP_MAX_IV_LENGTH];	/* working iv */
 	unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */
 	int num;				/* used by cfb/ofb/ctr mode */
 
 	void *app_data;		/* application stuff */
 	int key_len;		/* May change for variable length cipher */
 	unsigned long flags;	/* Various flags */
 	void *cipher_data; /* per EVP data */
 	int final_used;
 	int block_mask;
 	unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */
 	} /* EVP_CIPHER_CTX */;
 
 typedef struct evp_Encode_Ctx_st
 	{
 	int num;	/* number saved in a partial encode/decode */
 	int length;	/* The length is either the output line length
 			 * (in input bytes) or the shortest input line
 			 * length that is ok.  Once decoding begins,
 			 * the length is adjusted up each time a longer
 			 * line is decoded */
 	unsigned char enc_data[80];	/* data to encode */
 	int line_num;	/* number read on current line */
 	int expect_nl;
 	} EVP_ENCODE_CTX;
 
 /* Password based encryption function */
 typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
 		ASN1_TYPE *param, const EVP_CIPHER *cipher,
                 const EVP_MD *md, int en_de);
 
 #ifndef OPENSSL_NO_RSA
 #define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
 					(char *)(rsa))
 #endif
 
 #ifndef OPENSSL_NO_DSA
 #define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
 					(char *)(dsa))
 #endif
 
 #ifndef OPENSSL_NO_DH
 #define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
 					(char *)(dh))
 #endif
 
 #ifndef OPENSSL_NO_EC
 #define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
                                         (char *)(eckey))
 #endif
 
 /* Add some extra combinations */
 #define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
 #define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
 #define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
 #define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
 
 int EVP_MD_type(const EVP_MD *md);
 #define EVP_MD_nid(e)			EVP_MD_type(e)
 #define EVP_MD_name(e)			OBJ_nid2sn(EVP_MD_nid(e))
 int EVP_MD_pkey_type(const EVP_MD *md);	
 int EVP_MD_size(const EVP_MD *md);
 int EVP_MD_block_size(const EVP_MD *md);
 unsigned long EVP_MD_flags(const EVP_MD *md);
 
 const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
 #define EVP_MD_CTX_size(e)		EVP_MD_size(EVP_MD_CTX_md(e))
 #define EVP_MD_CTX_block_size(e)	EVP_MD_block_size(EVP_MD_CTX_md(e))
 #define EVP_MD_CTX_type(e)		EVP_MD_type(EVP_MD_CTX_md(e))
 
 int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
 #define EVP_CIPHER_name(e)		OBJ_nid2sn(EVP_CIPHER_nid(e))
 int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
 int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
 int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
 unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
 #define EVP_CIPHER_mode(e)		(EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
 
 const EVP_CIPHER * EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
 void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
 void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
 #define EVP_CIPHER_CTX_type(c)         EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
 unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
 #define EVP_CIPHER_CTX_mode(e)		(EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE)
 
 #define EVP_ENCODE_LENGTH(l)	(((l+2)/3*4)+(l/48+1)*2+80)
 #define EVP_DECODE_LENGTH(l)	((l+3)/4*3+80)
 
 #define EVP_SignInit_ex(a,b,c)		EVP_DigestInit_ex(a,b,c)
 #define EVP_SignInit(a,b)		EVP_DigestInit(a,b)
 #define EVP_SignUpdate(a,b,c)		EVP_DigestUpdate(a,b,c)
 #define	EVP_VerifyInit_ex(a,b,c)	EVP_DigestInit_ex(a,b,c)
 #define	EVP_VerifyInit(a,b)		EVP_DigestInit(a,b)
 #define	EVP_VerifyUpdate(a,b,c)		EVP_DigestUpdate(a,b,c)
 #define EVP_OpenUpdate(a,b,c,d,e)	EVP_DecryptUpdate(a,b,c,d,e)
 #define EVP_SealUpdate(a,b,c,d,e)	EVP_EncryptUpdate(a,b,c,d,e)	
 #define EVP_DigestSignUpdate(a,b,c)	EVP_DigestUpdate(a,b,c)
 #define EVP_DigestVerifyUpdate(a,b,c)	EVP_DigestUpdate(a,b,c)
 
 #ifdef CONST_STRICT
 void BIO_set_md(BIO *,const EVP_MD *md);
 #else
 # define BIO_set_md(b,md)		BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md)
 #endif
 #define BIO_get_md(b,mdp)		BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
 #define BIO_get_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
 #define BIO_set_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp)
 #define BIO_get_cipher_status(b)	BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
 #define BIO_get_cipher_ctx(b,c_pp)	BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
 
 int EVP_Cipher(EVP_CIPHER_CTX *c,
 		unsigned char *out,
 		const unsigned char *in,
 		unsigned int inl);
 
 #define EVP_add_cipher_alias(n,alias) \
 	OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
 #define EVP_add_digest_alias(n,alias) \
 	OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
 #define EVP_delete_cipher_alias(alias) \
 	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
 #define EVP_delete_digest_alias(alias) \
 	OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
 
 void	EVP_MD_CTX_init(EVP_MD_CTX *ctx);
 int	EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
 EVP_MD_CTX *EVP_MD_CTX_create(void);
 void	EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
 int     EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in);  
 void	EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
 void	EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
 int 	EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,int flags);
 int	EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
 int	EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
 			 size_t cnt);
 int	EVP_DigestFinal_ex(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
 int	EVP_Digest(const void *data, size_t count,
 		unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl);
 
 int     EVP_MD_CTX_copy(EVP_MD_CTX *out,const EVP_MD_CTX *in);  
 int	EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
 int	EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
 
 int	EVP_read_pw_string(char *buf,int length,const char *prompt,int verify);
 int	EVP_read_pw_string_min(char *buf,int minlen,int maxlen,const char *prompt,int verify);
 void	EVP_set_pw_prompt(const char *prompt);
 char *	EVP_get_pw_prompt(void);
 
 int	EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,
 		const unsigned char *salt, const unsigned char *data,
 		int datal, int count, unsigned char *key,unsigned char *iv);
 
 void	EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
 void	EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
 int 	EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx,int flags);
 
 int	EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
 		const unsigned char *key, const unsigned char *iv);
 int	EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
 		const unsigned char *key, const unsigned char *iv);
 int	EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		int *outl, const unsigned char *in, int inl);
 int	EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
 int	EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
 
 int	EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
 		const unsigned char *key, const unsigned char *iv);
 int	EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
 		const unsigned char *key, const unsigned char *iv);
 int	EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		int *outl, const unsigned char *in, int inl);
 int	EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
 int	EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
 
 int	EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
 		       const unsigned char *key,const unsigned char *iv,
 		       int enc);
 int	EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
 		       const unsigned char *key,const unsigned char *iv,
 		       int enc);
 int	EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
 		int *outl, const unsigned char *in, int inl);
 int	EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
 int	EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
 
 int	EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s,
 		EVP_PKEY *pkey);
 
 int	EVP_VerifyFinal(EVP_MD_CTX *ctx,const unsigned char *sigbuf,
 		unsigned int siglen,EVP_PKEY *pkey);
 
 int	EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
 			const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
 int	EVP_DigestSignFinal(EVP_MD_CTX *ctx,
 			unsigned char *sigret, size_t *siglen);
 
 int	EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
 			const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
 int	EVP_DigestVerifyFinal(EVP_MD_CTX *ctx,
 			unsigned char *sig, size_t siglen);
 
 int	EVP_OpenInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type,
 		const unsigned char *ek, int ekl, const unsigned char *iv,
 		EVP_PKEY *priv);
 int	EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
 
 int	EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
 		 unsigned char **ek, int *ekl, unsigned char *iv,
 		EVP_PKEY **pubk, int npubk);
 int	EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl);
 
 void	EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
 void	EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
 		const unsigned char *in,int inl);
 void	EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);
 int	EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
 
 void	EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
 int	EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
 		const unsigned char *in, int inl);
 int	EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
 		char *out, int *outl);
 int	EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
 
 void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
 int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
 void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
 int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
 
 #ifndef OPENSSL_NO_BIO
 BIO_METHOD *BIO_f_md(void);
 BIO_METHOD *BIO_f_base64(void);
 BIO_METHOD *BIO_f_cipher(void);
 BIO_METHOD *BIO_f_reliable(void);
 void BIO_set_cipher(BIO *b,const EVP_CIPHER *c,const unsigned char *k,
 		const unsigned char *i, int enc);
 #endif
 
 const EVP_MD *EVP_md_null(void);
 #ifndef OPENSSL_NO_MD2
 const EVP_MD *EVP_md2(void);
 #endif
 #ifndef OPENSSL_NO_MD4
 const EVP_MD *EVP_md4(void);
 #endif
 #ifndef OPENSSL_NO_MD5
 const EVP_MD *EVP_md5(void);
 #endif
 #ifndef OPENSSL_NO_SHA
 const EVP_MD *EVP_sha(void);
 const EVP_MD *EVP_sha1(void);
 const EVP_MD *EVP_dss(void);
 const EVP_MD *EVP_dss1(void);
 const EVP_MD *EVP_ecdsa(void);
 #endif
 #ifndef OPENSSL_NO_SHA256
 const EVP_MD *EVP_sha224(void);
 const EVP_MD *EVP_sha256(void);
 #endif
 #ifndef OPENSSL_NO_SHA512
 const EVP_MD *EVP_sha384(void);
 const EVP_MD *EVP_sha512(void);
 #endif
 #ifndef OPENSSL_NO_MDC2
 const EVP_MD *EVP_mdc2(void);
 #endif
 #ifndef OPENSSL_NO_RIPEMD
 const EVP_MD *EVP_ripemd160(void);
 #endif
 #ifndef OPENSSL_NO_WHIRLPOOL
 const EVP_MD *EVP_whirlpool(void);
 #endif
 const EVP_CIPHER *EVP_enc_null(void);		/* does nothing :-) */
 #ifndef OPENSSL_NO_DES
 const EVP_CIPHER *EVP_des_ecb(void);
 const EVP_CIPHER *EVP_des_ede(void);
 const EVP_CIPHER *EVP_des_ede3(void);
 const EVP_CIPHER *EVP_des_ede_ecb(void);
 const EVP_CIPHER *EVP_des_ede3_ecb(void);
 const EVP_CIPHER *EVP_des_cfb64(void);
 # define EVP_des_cfb EVP_des_cfb64
 const EVP_CIPHER *EVP_des_cfb1(void);
 const EVP_CIPHER *EVP_des_cfb8(void);
 const EVP_CIPHER *EVP_des_ede_cfb64(void);
 # define EVP_des_ede_cfb EVP_des_ede_cfb64
 #if 0
 const EVP_CIPHER *EVP_des_ede_cfb1(void);
 const EVP_CIPHER *EVP_des_ede_cfb8(void);
 #endif
 const EVP_CIPHER *EVP_des_ede3_cfb64(void);
 # define EVP_des_ede3_cfb EVP_des_ede3_cfb64
 const EVP_CIPHER *EVP_des_ede3_cfb1(void);
 const EVP_CIPHER *EVP_des_ede3_cfb8(void);
 const EVP_CIPHER *EVP_des_ofb(void);
 const EVP_CIPHER *EVP_des_ede_ofb(void);
 const EVP_CIPHER *EVP_des_ede3_ofb(void);
 const EVP_CIPHER *EVP_des_cbc(void);
 const EVP_CIPHER *EVP_des_ede_cbc(void);
 const EVP_CIPHER *EVP_des_ede3_cbc(void);
 const EVP_CIPHER *EVP_desx_cbc(void);
 /* This should now be supported through the dev_crypto ENGINE. But also, why are
  * rc4 and md5 declarations made here inside a "NO_DES" precompiler branch? */
 #if 0
 # ifdef OPENSSL_OPENBSD_DEV_CRYPTO
 const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void);
 const EVP_CIPHER *EVP_dev_crypto_rc4(void);
 const EVP_MD *EVP_dev_crypto_md5(void);
 # endif
 #endif
 #endif
 #ifndef OPENSSL_NO_RC4
 const EVP_CIPHER *EVP_rc4(void);
 const EVP_CIPHER *EVP_rc4_40(void);
 #ifndef OPENSSL_NO_MD5
 const EVP_CIPHER *EVP_rc4_hmac_md5(void);
 #endif
 #endif
 #ifndef OPENSSL_NO_IDEA
 const EVP_CIPHER *EVP_idea_ecb(void);
 const EVP_CIPHER *EVP_idea_cfb64(void);
 # define EVP_idea_cfb EVP_idea_cfb64
 const EVP_CIPHER *EVP_idea_ofb(void);
 const EVP_CIPHER *EVP_idea_cbc(void);
 #endif
 #ifndef OPENSSL_NO_RC2
 const EVP_CIPHER *EVP_rc2_ecb(void);
 const EVP_CIPHER *EVP_rc2_cbc(void);
 const EVP_CIPHER *EVP_rc2_40_cbc(void);
 const EVP_CIPHER *EVP_rc2_64_cbc(void);
 const EVP_CIPHER *EVP_rc2_cfb64(void);
 # define EVP_rc2_cfb EVP_rc2_cfb64
 const EVP_CIPHER *EVP_rc2_ofb(void);
 #endif
 #ifndef OPENSSL_NO_BF
 const EVP_CIPHER *EVP_bf_ecb(void);
 const EVP_CIPHER *EVP_bf_cbc(void);
 const EVP_CIPHER *EVP_bf_cfb64(void);
 # define EVP_bf_cfb EVP_bf_cfb64
 const EVP_CIPHER *EVP_bf_ofb(void);
 #endif
 #ifndef OPENSSL_NO_CAST
 const EVP_CIPHER *EVP_cast5_ecb(void);
 const EVP_CIPHER *EVP_cast5_cbc(void);
 const EVP_CIPHER *EVP_cast5_cfb64(void);
 # define EVP_cast5_cfb EVP_cast5_cfb64
 const EVP_CIPHER *EVP_cast5_ofb(void);
 #endif
 #ifndef OPENSSL_NO_RC5
 const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
 const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
 const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
 # define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
 const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
 #endif
 #ifndef OPENSSL_NO_AES
 const EVP_CIPHER *EVP_aes_128_ecb(void);
 const EVP_CIPHER *EVP_aes_128_cbc(void);
 const EVP_CIPHER *EVP_aes_128_cfb1(void);
 const EVP_CIPHER *EVP_aes_128_cfb8(void);
 const EVP_CIPHER *EVP_aes_128_cfb128(void);
 # define EVP_aes_128_cfb EVP_aes_128_cfb128
 const EVP_CIPHER *EVP_aes_128_ofb(void);
 const EVP_CIPHER *EVP_aes_128_ctr(void);
 const EVP_CIPHER *EVP_aes_128_ccm(void);
 const EVP_CIPHER *EVP_aes_128_gcm(void);
 const EVP_CIPHER *EVP_aes_128_xts(void);
 const EVP_CIPHER *EVP_aes_192_ecb(void);
 const EVP_CIPHER *EVP_aes_192_cbc(void);
 const EVP_CIPHER *EVP_aes_192_cfb1(void);
 const EVP_CIPHER *EVP_aes_192_cfb8(void);
 const EVP_CIPHER *EVP_aes_192_cfb128(void);
 # define EVP_aes_192_cfb EVP_aes_192_cfb128
 const EVP_CIPHER *EVP_aes_192_ofb(void);
 const EVP_CIPHER *EVP_aes_192_ctr(void);
 const EVP_CIPHER *EVP_aes_192_ccm(void);
 const EVP_CIPHER *EVP_aes_192_gcm(void);
 const EVP_CIPHER *EVP_aes_256_ecb(void);
 const EVP_CIPHER *EVP_aes_256_cbc(void);
 const EVP_CIPHER *EVP_aes_256_cfb1(void);
 const EVP_CIPHER *EVP_aes_256_cfb8(void);
 const EVP_CIPHER *EVP_aes_256_cfb128(void);
 # define EVP_aes_256_cfb EVP_aes_256_cfb128
 const EVP_CIPHER *EVP_aes_256_ofb(void);
 const EVP_CIPHER *EVP_aes_256_ctr(void);
 const EVP_CIPHER *EVP_aes_256_ccm(void);
 const EVP_CIPHER *EVP_aes_256_gcm(void);
 const EVP_CIPHER *EVP_aes_256_xts(void);
 #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
 const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
 const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
 #endif
 #endif
 #ifndef OPENSSL_NO_CAMELLIA
 const EVP_CIPHER *EVP_camellia_128_ecb(void);
 const EVP_CIPHER *EVP_camellia_128_cbc(void);
 const EVP_CIPHER *EVP_camellia_128_cfb1(void);
 const EVP_CIPHER *EVP_camellia_128_cfb8(void);
 const EVP_CIPHER *EVP_camellia_128_cfb128(void);
 # define EVP_camellia_128_cfb EVP_camellia_128_cfb128
 const EVP_CIPHER *EVP_camellia_128_ofb(void);
 const EVP_CIPHER *EVP_camellia_192_ecb(void);
 const EVP_CIPHER *EVP_camellia_192_cbc(void);
 const EVP_CIPHER *EVP_camellia_192_cfb1(void);
 const EVP_CIPHER *EVP_camellia_192_cfb8(void);
 const EVP_CIPHER *EVP_camellia_192_cfb128(void);
 # define EVP_camellia_192_cfb EVP_camellia_192_cfb128
 const EVP_CIPHER *EVP_camellia_192_ofb(void);
 const EVP_CIPHER *EVP_camellia_256_ecb(void);
 const EVP_CIPHER *EVP_camellia_256_cbc(void);
 const EVP_CIPHER *EVP_camellia_256_cfb1(void);
 const EVP_CIPHER *EVP_camellia_256_cfb8(void);
 const EVP_CIPHER *EVP_camellia_256_cfb128(void);
 # define EVP_camellia_256_cfb EVP_camellia_256_cfb128
 const EVP_CIPHER *EVP_camellia_256_ofb(void);
 #endif
 
 #ifndef OPENSSL_NO_SEED
 const EVP_CIPHER *EVP_seed_ecb(void);
 const EVP_CIPHER *EVP_seed_cbc(void);
 const EVP_CIPHER *EVP_seed_cfb128(void);
 # define EVP_seed_cfb EVP_seed_cfb128
 const EVP_CIPHER *EVP_seed_ofb(void);
 #endif
 
 void OPENSSL_add_all_algorithms_noconf(void);
 void OPENSSL_add_all_algorithms_conf(void);
 
 #ifdef OPENSSL_LOAD_CONF
 #define OpenSSL_add_all_algorithms() \
 		OPENSSL_add_all_algorithms_conf()
 #else
 #define OpenSSL_add_all_algorithms() \
 		OPENSSL_add_all_algorithms_noconf()
 #endif
 
 void OpenSSL_add_all_ciphers(void);
 void OpenSSL_add_all_digests(void);
 #define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
 #define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers()
 #define SSLeay_add_all_digests() OpenSSL_add_all_digests()
 
 int EVP_add_cipher(const EVP_CIPHER *cipher);
 int EVP_add_digest(const EVP_MD *digest);
 
 const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
 const EVP_MD *EVP_get_digestbyname(const char *name);
 void EVP_cleanup(void);
 
 void EVP_CIPHER_do_all(void (*fn)(const EVP_CIPHER *ciph,
 		const char *from, const char *to, void *x), void *arg);
 void EVP_CIPHER_do_all_sorted(void (*fn)(const EVP_CIPHER *ciph,
 		const char *from, const char *to, void *x), void *arg);
 
 void EVP_MD_do_all(void (*fn)(const EVP_MD *ciph,
 		const char *from, const char *to, void *x), void *arg);
 void EVP_MD_do_all_sorted(void (*fn)(const EVP_MD *ciph,
 		const char *from, const char *to, void *x), void *arg);
 
 int		EVP_PKEY_decrypt_old(unsigned char *dec_key,
 			const unsigned char *enc_key,int enc_key_len,
 			EVP_PKEY *private_key);
 int		EVP_PKEY_encrypt_old(unsigned char *enc_key,
 			const unsigned char *key,int key_len,
 			EVP_PKEY *pub_key);
 int		EVP_PKEY_type(int type);
 int		EVP_PKEY_id(const EVP_PKEY *pkey);
 int		EVP_PKEY_base_id(const EVP_PKEY *pkey);
 int		EVP_PKEY_bits(EVP_PKEY *pkey);
 int		EVP_PKEY_size(EVP_PKEY *pkey);
 int 		EVP_PKEY_set_type(EVP_PKEY *pkey,int type);
 int		EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
 int 		EVP_PKEY_assign(EVP_PKEY *pkey,int type,void *key);
 void *		EVP_PKEY_get0(EVP_PKEY *pkey);
 
 #ifndef OPENSSL_NO_RSA
 struct rsa_st;
 int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,struct rsa_st *key);
 struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
 #endif
 #ifndef OPENSSL_NO_DSA
 struct dsa_st;
 int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,struct dsa_st *key);
 struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
 #endif
 #ifndef OPENSSL_NO_DH
 struct dh_st;
 int EVP_PKEY_set1_DH(EVP_PKEY *pkey,struct dh_st *key);
 struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
 #endif
 #ifndef OPENSSL_NO_EC
 struct ec_key_st;
 int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey,struct ec_key_st *key);
 struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
 #endif
 
 EVP_PKEY *	EVP_PKEY_new(void);
 void		EVP_PKEY_free(EVP_PKEY *pkey);
 
 EVP_PKEY *	d2i_PublicKey(int type,EVP_PKEY **a, const unsigned char **pp,
 			long length);
 int		i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
 
 EVP_PKEY *	d2i_PrivateKey(int type,EVP_PKEY **a, const unsigned char **pp,
 			long length);
 EVP_PKEY *	d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
 			long length);
 int		i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
 
 int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
 int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
 int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode);
 int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
 
 int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
 
 int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
 				int indent, ASN1_PCTX *pctx);
 int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
 				int indent, ASN1_PCTX *pctx);
 int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
 				int indent, ASN1_PCTX *pctx);
 
 int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
 
 int EVP_CIPHER_type(const EVP_CIPHER *ctx);
 
 /* calls methods */
 int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
 int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
 
 /* These are used by EVP_CIPHER methods */
 int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
 int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
 
 /* PKCS5 password based encryption */
 int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
 			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
 			 int en_de);
 int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
 			   const unsigned char *salt, int saltlen, int iter,
 			   int keylen, unsigned char *out);
 int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
 			   const unsigned char *salt, int saltlen, int iter,
 			   const EVP_MD *digest,
 		      int keylen, unsigned char *out);
 int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
 			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
 			 int en_de);
 
 void PKCS5_PBE_add(void);
 
 int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
 	     ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
 
 /* PBE type */
 
 /* Can appear as the outermost AlgorithmIdentifier */
 #define EVP_PBE_TYPE_OUTER	0x0
 /* Is an PRF type OID */
 #define EVP_PBE_TYPE_PRF	0x1
 
 int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, int md_nid,
 	     EVP_PBE_KEYGEN *keygen);
 int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
 		    EVP_PBE_KEYGEN *keygen);
 int EVP_PBE_find(int type, int pbe_nid,
 			int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen);
 void EVP_PBE_cleanup(void);
 
 #define ASN1_PKEY_ALIAS		0x1
 #define ASN1_PKEY_DYNAMIC	0x2
 #define ASN1_PKEY_SIGPARAM_NULL	0x4
 
 #define ASN1_PKEY_CTRL_PKCS7_SIGN	0x1
 #define ASN1_PKEY_CTRL_PKCS7_ENCRYPT	0x2
 #define ASN1_PKEY_CTRL_DEFAULT_MD_NID	0x3
 #define ASN1_PKEY_CTRL_CMS_SIGN		0x5
 #define ASN1_PKEY_CTRL_CMS_ENVELOPE	0x7
 
 int EVP_PKEY_asn1_get_count(void);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
 					const char *str, int len);
 int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
 int EVP_PKEY_asn1_add_alias(int to, int from);
 int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, int *ppkey_flags,
 				const char **pinfo, const char **ppem_str,
 					const EVP_PKEY_ASN1_METHOD *ameth);
 
 const EVP_PKEY_ASN1_METHOD* EVP_PKEY_get0_asn1(EVP_PKEY *pkey);
 EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags,
 					const char *pem_str, const char *info);
 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, 
 			const EVP_PKEY_ASN1_METHOD *src);
 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
 void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
 		int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
 		int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
 		int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 		int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 							ASN1_PCTX *pctx),
 		int (*pkey_size)(const EVP_PKEY *pk),
 		int (*pkey_bits)(const EVP_PKEY *pk));
 void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
 		int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf),
 		int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
 		int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 							ASN1_PCTX *pctx));
 void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
 		int (*param_decode)(EVP_PKEY *pkey,
 				const unsigned char **pder, int derlen),
 		int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
 		int (*param_missing)(const EVP_PKEY *pk),
 		int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
 		int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 		int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 							ASN1_PCTX *pctx));
 
 void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
 		void (*pkey_free)(EVP_PKEY *pkey));
 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
 		int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
 							long arg1, void *arg2));
 
 
 #define EVP_PKEY_OP_UNDEFINED		0
 #define EVP_PKEY_OP_PARAMGEN		(1<<1)
 #define EVP_PKEY_OP_KEYGEN		(1<<2)
 #define EVP_PKEY_OP_SIGN		(1<<3)
 #define EVP_PKEY_OP_VERIFY		(1<<4)
 #define EVP_PKEY_OP_VERIFYRECOVER	(1<<5)
 #define EVP_PKEY_OP_SIGNCTX		(1<<6)
 #define EVP_PKEY_OP_VERIFYCTX		(1<<7)
 #define EVP_PKEY_OP_ENCRYPT		(1<<8)
 #define EVP_PKEY_OP_DECRYPT		(1<<9)
 #define EVP_PKEY_OP_DERIVE		(1<<10)
 
 #define EVP_PKEY_OP_TYPE_SIG	\
 	(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \
 		| EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX)
 
 #define EVP_PKEY_OP_TYPE_CRYPT \
 	(EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
 
 #define EVP_PKEY_OP_TYPE_NOGEN \
 	(EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
 
 #define EVP_PKEY_OP_TYPE_GEN \
 		(EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
 
 #define	 EVP_PKEY_CTX_set_signature_md(ctx, md)	\
 		EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,  \
 					EVP_PKEY_CTRL_MD, 0, (void *)md)
 
 #define EVP_PKEY_CTRL_MD		1
 #define EVP_PKEY_CTRL_PEER_KEY		2
 
 #define EVP_PKEY_CTRL_PKCS7_ENCRYPT	3
 #define EVP_PKEY_CTRL_PKCS7_DECRYPT	4
 
 #define EVP_PKEY_CTRL_PKCS7_SIGN	5
 
 #define EVP_PKEY_CTRL_SET_MAC_KEY	6
 
 #define EVP_PKEY_CTRL_DIGESTINIT	7
 
 /* Used by GOST key encryption in TLS */
 #define EVP_PKEY_CTRL_SET_IV 		8
 
 #define EVP_PKEY_CTRL_CMS_ENCRYPT	9
 #define EVP_PKEY_CTRL_CMS_DECRYPT	10
 #define EVP_PKEY_CTRL_CMS_SIGN		11
 
 #define EVP_PKEY_CTRL_CIPHER		12
 
 #define EVP_PKEY_ALG_CTRL		0x1000
 
 
 #define EVP_PKEY_FLAG_AUTOARGLEN	2
 /* Method handles all operations: don't assume any digest related
  * defaults.
  */
 #define EVP_PKEY_FLAG_SIGCTX_CUSTOM	4
 
 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
 EVP_PKEY_METHOD* EVP_PKEY_meth_new(int id, int flags);
 void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
 				const EVP_PKEY_METHOD *meth);
 void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
 void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
 int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 
 int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
 				int cmd, int p1, void *p2);
 int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
 						const char *value);
 
 int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
 
 EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
 				const unsigned char *key, int keylen);
 
 void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
 
 EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
 
 void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
 int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
 			unsigned char *sig, size_t *siglen,
 			const unsigned char *tbs, size_t tbslen);
 int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
 			const unsigned char *sig, size_t siglen,
 			const unsigned char *tbs, size_t tbslen);
 int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
 			unsigned char *rout, size_t *routlen,
 			const unsigned char *sig, size_t siglen);
 int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
 			unsigned char *out, size_t *outlen,
 			const unsigned char *in, size_t inlen);
 int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
 			unsigned char *out, size_t *outlen,
 			const unsigned char *in, size_t inlen);
 
 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
 int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
 
 typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
 
 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 
 void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
 EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx);
 
 int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx);
 
 void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
 	int (*init)(EVP_PKEY_CTX *ctx));
 
 void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
 	int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src));
 
 void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
 	void (*cleanup)(EVP_PKEY_CTX *ctx));
 
 void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
 	int (*paramgen_init)(EVP_PKEY_CTX *ctx),
 	int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
 
 void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
 	int (*keygen_init)(EVP_PKEY_CTX *ctx),
 	int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
 
 void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
 	int (*sign_init)(EVP_PKEY_CTX *ctx),
 	int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
 					const unsigned char *tbs, size_t tbslen));
 
 void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
 	int (*verify_init)(EVP_PKEY_CTX *ctx),
 	int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
 					const unsigned char *tbs, size_t tbslen));
 
 void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
 	int (*verify_recover_init)(EVP_PKEY_CTX *ctx),
 	int (*verify_recover)(EVP_PKEY_CTX *ctx,
 					unsigned char *sig, size_t *siglen,
 					const unsigned char *tbs, size_t tbslen));
 
 void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
 	int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
 	int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
 					EVP_MD_CTX *mctx));
 
 void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
 	int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
 	int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig,int siglen,
 					EVP_MD_CTX *mctx));
 
 void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
 	int (*encrypt_init)(EVP_PKEY_CTX *ctx),
 	int (*encryptfn)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
 					const unsigned char *in, size_t inlen));
 
 void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
 	int (*decrypt_init)(EVP_PKEY_CTX *ctx),
 	int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
 					const unsigned char *in, size_t inlen));
 
 void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
 	int (*derive_init)(EVP_PKEY_CTX *ctx),
 	int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen));
 
 void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
 	int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2),
 	int (*ctrl_str)(EVP_PKEY_CTX *ctx,
 					const char *type, const char *value));
 
 void EVP_add_alg_module(void);
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
 void ERR_load_EVP_strings(void);
 
 /* Error codes for the EVP functions. */
 
 /* Function codes. */
 #define EVP_F_AESNI_INIT_KEY				 165
 #define EVP_F_AESNI_XTS_CIPHER				 176
 #define EVP_F_AES_INIT_KEY				 133
 #define EVP_F_AES_XTS					 172
 #define EVP_F_AES_XTS_CIPHER				 175
 #define EVP_F_ALG_MODULE_INIT				 177
 #define EVP_F_CAMELLIA_INIT_KEY				 159
 #define EVP_F_CMAC_INIT					 173
 #define EVP_F_D2I_PKEY					 100
 #define EVP_F_DO_SIGVER_INIT				 161
 #define EVP_F_DSAPKEY2PKCS8				 134
 #define EVP_F_DSA_PKEY2PKCS8				 135
 #define EVP_F_ECDSA_PKEY2PKCS8				 129
 #define EVP_F_ECKEY_PKEY2PKCS8				 132
 #define EVP_F_EVP_CIPHERINIT_EX				 123
 #define EVP_F_EVP_CIPHER_CTX_COPY			 163
 #define EVP_F_EVP_CIPHER_CTX_CTRL			 124
 #define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
 #define EVP_F_EVP_DECRYPTFINAL_EX			 101
 #define EVP_F_EVP_DIGESTINIT_EX				 128
 #define EVP_F_EVP_ENCRYPTFINAL_EX			 127
 #define EVP_F_EVP_MD_CTX_COPY_EX			 110
 #define EVP_F_EVP_MD_SIZE				 162
 #define EVP_F_EVP_OPENINIT				 102
 #define EVP_F_EVP_PBE_ALG_ADD				 115
 #define EVP_F_EVP_PBE_ALG_ADD_TYPE			 160
 #define EVP_F_EVP_PBE_CIPHERINIT			 116
 #define EVP_F_EVP_PKCS82PKEY				 111
 #define EVP_F_EVP_PKCS82PKEY_BROKEN			 136
 #define EVP_F_EVP_PKEY2PKCS8_BROKEN			 113
 #define EVP_F_EVP_PKEY_COPY_PARAMETERS			 103
 #define EVP_F_EVP_PKEY_CTX_CTRL				 137
 #define EVP_F_EVP_PKEY_CTX_CTRL_STR			 150
 #define EVP_F_EVP_PKEY_CTX_DUP				 156
 #define EVP_F_EVP_PKEY_DECRYPT				 104
 #define EVP_F_EVP_PKEY_DECRYPT_INIT			 138
 #define EVP_F_EVP_PKEY_DECRYPT_OLD			 151
 #define EVP_F_EVP_PKEY_DERIVE				 153
 #define EVP_F_EVP_PKEY_DERIVE_INIT			 154
 #define EVP_F_EVP_PKEY_DERIVE_SET_PEER			 155
 #define EVP_F_EVP_PKEY_ENCRYPT				 105
 #define EVP_F_EVP_PKEY_ENCRYPT_INIT			 139
 #define EVP_F_EVP_PKEY_ENCRYPT_OLD			 152
 #define EVP_F_EVP_PKEY_GET1_DH				 119
 #define EVP_F_EVP_PKEY_GET1_DSA				 120
 #define EVP_F_EVP_PKEY_GET1_ECDSA			 130
 #define EVP_F_EVP_PKEY_GET1_EC_KEY			 131
 #define EVP_F_EVP_PKEY_GET1_RSA				 121
 #define EVP_F_EVP_PKEY_KEYGEN				 146
 #define EVP_F_EVP_PKEY_KEYGEN_INIT			 147
 #define EVP_F_EVP_PKEY_NEW				 106
 #define EVP_F_EVP_PKEY_PARAMGEN				 148
 #define EVP_F_EVP_PKEY_PARAMGEN_INIT			 149
 #define EVP_F_EVP_PKEY_SIGN				 140
 #define EVP_F_EVP_PKEY_SIGN_INIT			 141
 #define EVP_F_EVP_PKEY_VERIFY				 142
 #define EVP_F_EVP_PKEY_VERIFY_INIT			 143
 #define EVP_F_EVP_PKEY_VERIFY_RECOVER			 144
 #define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT		 145
 #define EVP_F_EVP_RIJNDAEL				 126
 #define EVP_F_EVP_SIGNFINAL				 107
 #define EVP_F_EVP_VERIFYFINAL				 108
 #define EVP_F_FIPS_CIPHERINIT				 166
 #define EVP_F_FIPS_CIPHER_CTX_COPY			 170
 #define EVP_F_FIPS_CIPHER_CTX_CTRL			 167
 #define EVP_F_FIPS_CIPHER_CTX_SET_KEY_LENGTH		 171
 #define EVP_F_FIPS_DIGESTINIT				 168
 #define EVP_F_FIPS_MD_CTX_COPY				 169
 #define EVP_F_HMAC_INIT_EX				 174
 #define EVP_F_INT_CTX_NEW				 157
 #define EVP_F_PKCS5_PBE_KEYIVGEN			 117
 #define EVP_F_PKCS5_V2_PBE_KEYIVGEN			 118
 #define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN			 164
 #define EVP_F_PKCS8_SET_BROKEN				 112
 #define EVP_F_PKEY_SET_TYPE				 158
 #define EVP_F_RC2_MAGIC_TO_METH				 109
 #define EVP_F_RC5_CTRL					 125
 
 /* Reason codes. */
 #define EVP_R_AES_IV_SETUP_FAILED			 162
 #define EVP_R_AES_KEY_SETUP_FAILED			 143
 #define EVP_R_ASN1_LIB					 140
 #define EVP_R_BAD_BLOCK_LENGTH				 136
 #define EVP_R_BAD_DECRYPT				 100
 #define EVP_R_BAD_KEY_LENGTH				 137
 #define EVP_R_BN_DECODE_ERROR				 112
 #define EVP_R_BN_PUBKEY_ERROR				 113
 #define EVP_R_BUFFER_TOO_SMALL				 155
 #define EVP_R_CAMELLIA_KEY_SETUP_FAILED			 157
 #define EVP_R_CIPHER_PARAMETER_ERROR			 122
 #define EVP_R_COMMAND_NOT_SUPPORTED			 147
 #define EVP_R_CTRL_NOT_IMPLEMENTED			 132
 #define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED		 133
 #define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH		 138
 #define EVP_R_DECODE_ERROR				 114
 #define EVP_R_DIFFERENT_KEY_TYPES			 101
 #define EVP_R_DIFFERENT_PARAMETERS			 153
 #define EVP_R_DISABLED_FOR_FIPS				 163
 #define EVP_R_ENCODE_ERROR				 115
 #define EVP_R_ERROR_LOADING_SECTION			 165
 #define EVP_R_ERROR_SETTING_FIPS_MODE			 166
 #define EVP_R_EVP_PBE_CIPHERINIT_ERROR			 119
 #define EVP_R_EXPECTING_AN_RSA_KEY			 127
 #define EVP_R_EXPECTING_A_DH_KEY			 128
 #define EVP_R_EXPECTING_A_DSA_KEY			 129
 #define EVP_R_EXPECTING_A_ECDSA_KEY			 141
 #define EVP_R_EXPECTING_A_EC_KEY			 142
 #define EVP_R_FIPS_MODE_NOT_SUPPORTED			 167
 #define EVP_R_INITIALIZATION_ERROR			 134
 #define EVP_R_INPUT_NOT_INITIALIZED			 111
 #define EVP_R_INVALID_DIGEST				 152
 #define EVP_R_INVALID_FIPS_MODE				 168
 #define EVP_R_INVALID_KEY_LENGTH			 130
 #define EVP_R_INVALID_OPERATION				 148
 #define EVP_R_IV_TOO_LARGE				 102
 #define EVP_R_KEYGEN_FAILURE				 120
 #define EVP_R_MESSAGE_DIGEST_IS_NULL			 159
 #define EVP_R_METHOD_NOT_SUPPORTED			 144
 #define EVP_R_MISSING_PARAMETERS			 103
 #define EVP_R_NO_CIPHER_SET				 131
 #define EVP_R_NO_DEFAULT_DIGEST				 158
 #define EVP_R_NO_DIGEST_SET				 139
 #define EVP_R_NO_DSA_PARAMETERS				 116
 #define EVP_R_NO_KEY_SET				 154
 #define EVP_R_NO_OPERATION_SET				 149
 #define EVP_R_NO_SIGN_FUNCTION_CONFIGURED		 104
 #define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED		 105
 #define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE	 150
 #define EVP_R_OPERATON_NOT_INITIALIZED			 151
 #define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE			 117
 #define EVP_R_PRIVATE_KEY_DECODE_ERROR			 145
 #define EVP_R_PRIVATE_KEY_ENCODE_ERROR			 146
 #define EVP_R_PUBLIC_KEY_NOT_RSA			 106
 #define EVP_R_TOO_LARGE					 164
 #define EVP_R_UNKNOWN_CIPHER				 160
 #define EVP_R_UNKNOWN_DIGEST				 161
 #define EVP_R_UNKNOWN_OPTION				 169
 #define EVP_R_UNKNOWN_PBE_ALGORITHM			 121
 #define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS		 135
 #define EVP_R_UNSUPPORTED_ALGORITHM			 156
 #define EVP_R_UNSUPPORTED_CIPHER			 107
 #define EVP_R_UNSUPPORTED_KEYLENGTH			 123
 #define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION	 124
 #define EVP_R_UNSUPPORTED_KEY_SIZE			 108
 #define EVP_R_UNSUPPORTED_PRF				 125
 #define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM		 118
 #define EVP_R_UNSUPPORTED_SALT_TYPE			 126
 #define EVP_R_WRONG_FINAL_BLOCK_LENGTH			 109
 #define EVP_R_WRONG_PUBLIC_KEY_TYPE			 110
 
 #ifdef  __cplusplus
 }
 #endif
 #endif
Index: releng/10.1/crypto/openssl/crypto/hmac/hmac.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/hmac/hmac.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/hmac/hmac.c	(revision 284295)
@@ -1,251 +1,252 @@
 /* crypto/hmac/hmac.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 
 #ifdef OPENSSL_FIPS
 #include 
 #endif
 
 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
 		  const EVP_MD *md, ENGINE *impl)
 	{
 	int i,j,reset=0;
 	unsigned char pad[HMAC_MAX_MD_CBLOCK];
 
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode())
 		{
 		/* If we have an ENGINE need to allow non FIPS */
 		if ((impl || ctx->i_ctx.engine)
 			&&  !(ctx->i_ctx.flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW))
 			{
 			EVPerr(EVP_F_HMAC_INIT_EX, EVP_R_DISABLED_FOR_FIPS);
 			return 0;
 			}
 		/* Other algorithm blocking will be done in FIPS_cmac_init,
 		 * via FIPS_hmac_init_ex().
 		 */
 		if (!impl && !ctx->i_ctx.engine)
 			return FIPS_hmac_init_ex(ctx, key, len, md, NULL);
 		}
 #endif
 
 	if (md != NULL)
 		{
 		reset=1;
 		ctx->md=md;
 		}
 	else
 		md=ctx->md;
 
 	if (key != NULL)
 		{
 		reset=1;
 		j=EVP_MD_block_size(md);
 		OPENSSL_assert(j <= (int)sizeof(ctx->key));
 		if (j < len)
 			{
 			if (!EVP_DigestInit_ex(&ctx->md_ctx,md, impl))
 				goto err;
 			if (!EVP_DigestUpdate(&ctx->md_ctx,key,len))
 				goto err;
 			if (!EVP_DigestFinal_ex(&(ctx->md_ctx),ctx->key,
 				&ctx->key_length))
 				goto err;
 			}
 		else
 			{
 			OPENSSL_assert(len>=0 && len<=(int)sizeof(ctx->key));
 			memcpy(ctx->key,key,len);
 			ctx->key_length=len;
 			}
 		if(ctx->key_length != HMAC_MAX_MD_CBLOCK)
 			memset(&ctx->key[ctx->key_length], 0,
 				HMAC_MAX_MD_CBLOCK - ctx->key_length);
 		}
 
 	if (reset)	
 		{
 		for (i=0; ikey[i];
 		if (!EVP_DigestInit_ex(&ctx->i_ctx,md, impl))
 			goto err;
 		if (!EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md)))
 			goto err;
 
 		for (i=0; ikey[i];
 		if (!EVP_DigestInit_ex(&ctx->o_ctx,md, impl))
 			goto err;
 		if (!EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md)))
 			goto err;
 		}
 	if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx))
 			goto err;
 	return 1;
 	err:
 	return 0;
 	}
 
 int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
 	{
 	if(key && md)
 	    HMAC_CTX_init(ctx);
 	return HMAC_Init_ex(ctx,key,len,md, NULL);
 	}
 
 int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
 	{
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode() && !ctx->i_ctx.engine)
 		return FIPS_hmac_update(ctx, data, len);
 #endif
 	return EVP_DigestUpdate(&ctx->md_ctx,data,len);
 	}
 
 int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
 	{
 	unsigned int i;
 	unsigned char buf[EVP_MAX_MD_SIZE];
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode() && !ctx->i_ctx.engine)
 		return FIPS_hmac_final(ctx, md, len);
 #endif
 
 	if (!EVP_DigestFinal_ex(&ctx->md_ctx,buf,&i))
 		goto err;
 	if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->o_ctx))
 		goto err;
 	if (!EVP_DigestUpdate(&ctx->md_ctx,buf,i))
 		goto err;
 	if (!EVP_DigestFinal_ex(&ctx->md_ctx,md,len))
 		goto err;
 	return 1;
 	err:
 	return 0;
 	}
 
 void HMAC_CTX_init(HMAC_CTX *ctx)
 	{
 	EVP_MD_CTX_init(&ctx->i_ctx);
 	EVP_MD_CTX_init(&ctx->o_ctx);
 	EVP_MD_CTX_init(&ctx->md_ctx);
 	}
 
 int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
 	{
 	if (!EVP_MD_CTX_copy(&dctx->i_ctx, &sctx->i_ctx))
 		goto err;
 	if (!EVP_MD_CTX_copy(&dctx->o_ctx, &sctx->o_ctx))
 		goto err;
 	if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx))
 		goto err;
 	memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK);
 	dctx->key_length = sctx->key_length;
 	dctx->md = sctx->md;
 	return 1;
 	err:
 	return 0;
 	}
 
 void HMAC_CTX_cleanup(HMAC_CTX *ctx)
 	{
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode() && !ctx->i_ctx.engine)
 		{
 		FIPS_hmac_ctx_cleanup(ctx);
 		return;
 		}
 #endif
 	EVP_MD_CTX_cleanup(&ctx->i_ctx);
 	EVP_MD_CTX_cleanup(&ctx->o_ctx);
 	EVP_MD_CTX_cleanup(&ctx->md_ctx);
 	memset(ctx,0,sizeof *ctx);
 	}
 
 unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
 		    const unsigned char *d, size_t n, unsigned char *md,
 		    unsigned int *md_len)
 	{
 	HMAC_CTX c;
 	static unsigned char m[EVP_MAX_MD_SIZE];
 
 	if (md == NULL) md=m;
 	HMAC_CTX_init(&c);
 	if (!HMAC_Init(&c,key,key_len,evp_md))
 		goto err;
 	if (!HMAC_Update(&c,d,n))
 		goto err;
 	if (!HMAC_Final(&c,md,md_len))
 		goto err;
 	HMAC_CTX_cleanup(&c);
 	return md;
 	err:
+    HMAC_CTX_cleanup(&c);
 	return NULL;
 	}
 
 void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
 	{
 	EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
 	EVP_MD_CTX_set_flags(&ctx->o_ctx, flags);
 	EVP_MD_CTX_set_flags(&ctx->md_ctx, flags);
 	}
Index: releng/10.1/crypto/openssl/crypto/modes/gcm128.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/modes/gcm128.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/modes/gcm128.c	(revision 284295)
@@ -1,1905 +1,1905 @@
 /* ====================================================================
  * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  */
 
 #define OPENSSL_FIPSAPI
 
 #include 
 #include "modes_lcl.h"
 #include 
 
 #ifndef MODES_DEBUG
 # ifndef NDEBUG
 #  define NDEBUG
 # endif
 #endif
 #include 
 
 #if defined(BSWAP4) && defined(STRICT_ALIGNMENT)
 /* redefine, because alignment is ensured */
 #undef	GETU32
 #define	GETU32(p)	BSWAP4(*(const u32 *)(p))
 #undef	PUTU32
 #define	PUTU32(p,v)	*(u32 *)(p) = BSWAP4(v)
 #endif
 
 #define	PACK(s)		((size_t)(s)<<(sizeof(size_t)*8-16))
 #define REDUCE1BIT(V)	do { \
 	if (sizeof(size_t)==8) { \
 		u64 T = U64(0xe100000000000000) & (0-(V.lo&1)); \
 		V.lo  = (V.hi<<63)|(V.lo>>1); \
 		V.hi  = (V.hi>>1 )^T; \
 	} \
 	else { \
 		u32 T = 0xe1000000U & (0-(u32)(V.lo&1)); \
 		V.lo  = (V.hi<<63)|(V.lo>>1); \
 		V.hi  = (V.hi>>1 )^((u64)T<<32); \
 	} \
 } while(0)
 
 /*
  * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
  * never be set to 8. 8 is effectively reserved for testing purposes.
  * TABLE_BITS>1 are lookup-table-driven implementations referred to as
  * "Shoup's" in GCM specification. In other words OpenSSL does not cover
  * whole spectrum of possible table driven implementations. Why? In
  * non-"Shoup's" case memory access pattern is segmented in such manner,
  * that it's trivial to see that cache timing information can reveal
  * fair portion of intermediate hash value. Given that ciphertext is
  * always available to attacker, it's possible for him to attempt to
  * deduce secret parameter H and if successful, tamper with messages
  * [which is nothing but trivial in CTR mode]. In "Shoup's" case it's
  * not as trivial, but there is no reason to believe that it's resistant
  * to cache-timing attack. And the thing about "8-bit" implementation is
  * that it consumes 16 (sixteen) times more memory, 4KB per individual
  * key + 1KB shared. Well, on pros side it should be twice as fast as
  * "4-bit" version. And for gcc-generated x86[_64] code, "8-bit" version
  * was observed to run ~75% faster, closer to 100% for commercial
  * compilers... Yet "4-bit" procedure is preferred, because it's
  * believed to provide better security-performance balance and adequate
  * all-round performance. "All-round" refers to things like:
  *
  * - shorter setup time effectively improves overall timing for
  *   handling short messages;
  * - larger table allocation can become unbearable because of VM
  *   subsystem penalties (for example on Windows large enough free
  *   results in VM working set trimming, meaning that consequent
  *   malloc would immediately incur working set expansion);
  * - larger table has larger cache footprint, which can affect
  *   performance of other code paths (not necessarily even from same
  *   thread in Hyper-Threading world);
  *
  * Value of 1 is not appropriate for performance reasons.
  */
 #if	TABLE_BITS==8
 
 static void gcm_init_8bit(u128 Htable[256], u64 H[2])
 {
 	int  i, j;
 	u128 V;
 
 	Htable[0].hi = 0;
 	Htable[0].lo = 0;
 	V.hi = H[0];
 	V.lo = H[1];
 
 	for (Htable[128]=V, i=64; i>0; i>>=1) {
 		REDUCE1BIT(V);
 		Htable[i] = V;
 	}
 
 	for (i=2; i<256; i<<=1) {
 		u128 *Hi = Htable+i, H0 = *Hi;
 		for (j=1; j>8);
 		Z.hi = (Z.hi>>8);
 		if (sizeof(size_t)==8)
 			Z.hi ^= rem_8bit[rem];
 		else
 			Z.hi ^= (u64)rem_8bit[rem]<<32;
 	}
 
 	if (is_endian.little) {
 #ifdef BSWAP8
 		Xi[0] = BSWAP8(Z.hi);
 		Xi[1] = BSWAP8(Z.lo);
 #else
 		u8 *p = (u8 *)Xi;
 		u32 v;
 		v = (u32)(Z.hi>>32);	PUTU32(p,v);
 		v = (u32)(Z.hi);	PUTU32(p+4,v);
 		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
 		v = (u32)(Z.lo);	PUTU32(p+12,v);
 #endif
 	}
 	else {
 		Xi[0] = Z.hi;
 		Xi[1] = Z.lo;
 	}
 }
 #define GCM_MUL(ctx,Xi)   gcm_gmult_8bit(ctx->Xi.u,ctx->Htable)
 
 #elif	TABLE_BITS==4
 
 static void gcm_init_4bit(u128 Htable[16], u64 H[2])
 {
 	u128 V;
 #if defined(OPENSSL_SMALL_FOOTPRINT)
 	int  i;
 #endif
 
 	Htable[0].hi = 0;
 	Htable[0].lo = 0;
 	V.hi = H[0];
 	V.lo = H[1];
 
 #if defined(OPENSSL_SMALL_FOOTPRINT)
 	for (Htable[8]=V, i=4; i>0; i>>=1) {
 		REDUCE1BIT(V);
 		Htable[i] = V;
 	}
 
 	for (i=2; i<16; i<<=1) {
 		u128 *Hi = Htable+i;
 		int   j;
 		for (V=*Hi, j=1; j>32;
 			Htable[j].lo = V.hi<<32|V.hi>>32;
 		}
 	}
 #endif
 }
 
 #ifndef GHASH_ASM
 static const size_t rem_4bit[16] = {
 	PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460),
 	PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0),
 	PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560),
 	PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0) };
 
 static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
 {
 	u128 Z;
 	int cnt = 15;
 	size_t rem, nlo, nhi;
 	const union { long one; char little; } is_endian = {1};
 
 	nlo  = ((const u8 *)Xi)[15];
 	nhi  = nlo>>4;
 	nlo &= 0xf;
 
 	Z.hi = Htable[nlo].hi;
 	Z.lo = Htable[nlo].lo;
 
 	while (1) {
 		rem  = (size_t)Z.lo&0xf;
 		Z.lo = (Z.hi<<60)|(Z.lo>>4);
 		Z.hi = (Z.hi>>4);
 		if (sizeof(size_t)==8)
 			Z.hi ^= rem_4bit[rem];
 		else
 			Z.hi ^= (u64)rem_4bit[rem]<<32;
 
 		Z.hi ^= Htable[nhi].hi;
 		Z.lo ^= Htable[nhi].lo;
 
 		if (--cnt<0)		break;
 
 		nlo  = ((const u8 *)Xi)[cnt];
 		nhi  = nlo>>4;
 		nlo &= 0xf;
 
 		rem  = (size_t)Z.lo&0xf;
 		Z.lo = (Z.hi<<60)|(Z.lo>>4);
 		Z.hi = (Z.hi>>4);
 		if (sizeof(size_t)==8)
 			Z.hi ^= rem_4bit[rem];
 		else
 			Z.hi ^= (u64)rem_4bit[rem]<<32;
 
 		Z.hi ^= Htable[nlo].hi;
 		Z.lo ^= Htable[nlo].lo;
 	}
 
 	if (is_endian.little) {
 #ifdef BSWAP8
 		Xi[0] = BSWAP8(Z.hi);
 		Xi[1] = BSWAP8(Z.lo);
 #else
 		u8 *p = (u8 *)Xi;
 		u32 v;
 		v = (u32)(Z.hi>>32);	PUTU32(p,v);
 		v = (u32)(Z.hi);	PUTU32(p+4,v);
 		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
 		v = (u32)(Z.lo);	PUTU32(p+12,v);
 #endif
 	}
 	else {
 		Xi[0] = Z.hi;
 		Xi[1] = Z.lo;
 	}
 }
 
 #if !defined(OPENSSL_SMALL_FOOTPRINT)
 /*
  * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
  * details... Compiler-generated code doesn't seem to give any
  * performance improvement, at least not on x86[_64]. It's here
  * mostly as reference and a placeholder for possible future
  * non-trivial optimization[s]...
  */
 static void gcm_ghash_4bit(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)
 {
     u128 Z;
     int cnt;
     size_t rem, nlo, nhi;
     const union { long one; char little; } is_endian = {1};
 
 #if 1
     do {
 	cnt  = 15;
 	nlo  = ((const u8 *)Xi)[15];
 	nlo ^= inp[15];
 	nhi  = nlo>>4;
 	nlo &= 0xf;
 
 	Z.hi = Htable[nlo].hi;
 	Z.lo = Htable[nlo].lo;
 
 	while (1) {
 		rem  = (size_t)Z.lo&0xf;
 		Z.lo = (Z.hi<<60)|(Z.lo>>4);
 		Z.hi = (Z.hi>>4);
 		if (sizeof(size_t)==8)
 			Z.hi ^= rem_4bit[rem];
 		else
 			Z.hi ^= (u64)rem_4bit[rem]<<32;
 
 		Z.hi ^= Htable[nhi].hi;
 		Z.lo ^= Htable[nhi].lo;
 
 		if (--cnt<0)		break;
 
 		nlo  = ((const u8 *)Xi)[cnt];
 		nlo ^= inp[cnt];
 		nhi  = nlo>>4;
 		nlo &= 0xf;
 
 		rem  = (size_t)Z.lo&0xf;
 		Z.lo = (Z.hi<<60)|(Z.lo>>4);
 		Z.hi = (Z.hi>>4);
 		if (sizeof(size_t)==8)
 			Z.hi ^= rem_4bit[rem];
 		else
 			Z.hi ^= (u64)rem_4bit[rem]<<32;
 
 		Z.hi ^= Htable[nlo].hi;
 		Z.lo ^= Htable[nlo].lo;
 	}
 #else
     /*
      * Extra 256+16 bytes per-key plus 512 bytes shared tables
      * [should] give ~50% improvement... One could have PACK()-ed
      * the rem_8bit even here, but the priority is to minimize
      * cache footprint...
      */ 
     u128 Hshr4[16];	/* Htable shifted right by 4 bits */
     u8   Hshl4[16];	/* Htable shifted left  by 4 bits */
     static const unsigned short rem_8bit[256] = {
 	0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E,
 	0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E,
 	0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E,
 	0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E,
 	0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E,
 	0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E,
 	0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E,
 	0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E,
 	0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE,
 	0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE,
 	0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE,
 	0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE,
 	0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E,
 	0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E,
 	0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE,
 	0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE,
 	0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E,
 	0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E,
 	0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E,
 	0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E,
 	0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E,
 	0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E,
 	0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E,
 	0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E,
 	0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE,
 	0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE,
 	0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE,
 	0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE,
 	0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E,
 	0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E,
 	0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE,
 	0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE };
     /*
      * This pre-processing phase slows down procedure by approximately
      * same time as it makes each loop spin faster. In other words
      * single block performance is approximately same as straightforward
      * "4-bit" implementation, and then it goes only faster...
      */
     for (cnt=0; cnt<16; ++cnt) {
 	Z.hi = Htable[cnt].hi;
 	Z.lo = Htable[cnt].lo;
 	Hshr4[cnt].lo = (Z.hi<<60)|(Z.lo>>4);
 	Hshr4[cnt].hi = (Z.hi>>4);
 	Hshl4[cnt]    = (u8)(Z.lo<<4);
     }
 
     do {
 	for (Z.lo=0, Z.hi=0, cnt=15; cnt; --cnt) {
 		nlo  = ((const u8 *)Xi)[cnt];
 		nlo ^= inp[cnt];
 		nhi  = nlo>>4;
 		nlo &= 0xf;
 
 		Z.hi ^= Htable[nlo].hi;
 		Z.lo ^= Htable[nlo].lo;
 
 		rem = (size_t)Z.lo&0xff;
 
 		Z.lo = (Z.hi<<56)|(Z.lo>>8);
 		Z.hi = (Z.hi>>8);
 
 		Z.hi ^= Hshr4[nhi].hi;
 		Z.lo ^= Hshr4[nhi].lo;
 		Z.hi ^= (u64)rem_8bit[rem^Hshl4[nhi]]<<48;
 	}
 
 	nlo  = ((const u8 *)Xi)[0];
 	nlo ^= inp[0];
 	nhi  = nlo>>4;
 	nlo &= 0xf;
 
 	Z.hi ^= Htable[nlo].hi;
 	Z.lo ^= Htable[nlo].lo;
 
 	rem = (size_t)Z.lo&0xf;
 
 	Z.lo = (Z.hi<<60)|(Z.lo>>4);
 	Z.hi = (Z.hi>>4);
 
 	Z.hi ^= Htable[nhi].hi;
 	Z.lo ^= Htable[nhi].lo;
 	Z.hi ^= ((u64)rem_8bit[rem<<4])<<48;
 #endif
 
 	if (is_endian.little) {
 #ifdef BSWAP8
 		Xi[0] = BSWAP8(Z.hi);
 		Xi[1] = BSWAP8(Z.lo);
 #else
 		u8 *p = (u8 *)Xi;
 		u32 v;
 		v = (u32)(Z.hi>>32);	PUTU32(p,v);
 		v = (u32)(Z.hi);	PUTU32(p+4,v);
 		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
 		v = (u32)(Z.lo);	PUTU32(p+12,v);
 #endif
 	}
 	else {
 		Xi[0] = Z.hi;
 		Xi[1] = Z.lo;
 	}
     } while (inp+=16, len-=16);
 }
 #endif
 #else
 void gcm_gmult_4bit(u64 Xi[2],const u128 Htable[16]);
 void gcm_ghash_4bit(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
 #endif
 
 #define GCM_MUL(ctx,Xi)   gcm_gmult_4bit(ctx->Xi.u,ctx->Htable)
 #if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT)
 #define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len)
 /* GHASH_CHUNK is "stride parameter" missioned to mitigate cache
  * trashing effect. In other words idea is to hash data while it's
  * still in L1 cache after encryption pass... */
 #define GHASH_CHUNK       (3*1024)
 #endif
 
 #else	/* TABLE_BITS */
 
 static void gcm_gmult_1bit(u64 Xi[2],const u64 H[2])
 {
 	u128 V,Z = { 0,0 };
 	long X;
 	int  i,j;
 	const long *xi = (const long *)Xi;
 	const union { long one; char little; } is_endian = {1};
 
 	V.hi = H[0];	/* H is in host byte order, no byte swapping */
 	V.lo = H[1];
 
 	for (j=0; j<16/sizeof(long); ++j) {
 		if (is_endian.little) {
 			if (sizeof(long)==8) {
 #ifdef BSWAP8
 				X = (long)(BSWAP8(xi[j]));
 #else
 				const u8 *p = (const u8 *)(xi+j);
 				X = (long)((u64)GETU32(p)<<32|GETU32(p+4));
 #endif
 			}
 			else {
 				const u8 *p = (const u8 *)(xi+j);
 				X = (long)GETU32(p);
 			}
 		}
 		else
 			X = xi[j];
 
 		for (i=0; i<8*sizeof(long); ++i, X<<=1) {
 			u64 M = (u64)(X>>(8*sizeof(long)-1));
 			Z.hi ^= V.hi&M;
 			Z.lo ^= V.lo&M;
 
 			REDUCE1BIT(V);
 		}
 	}
 
 	if (is_endian.little) {
 #ifdef BSWAP8
 		Xi[0] = BSWAP8(Z.hi);
 		Xi[1] = BSWAP8(Z.lo);
 #else
 		u8 *p = (u8 *)Xi;
 		u32 v;
 		v = (u32)(Z.hi>>32);	PUTU32(p,v);
 		v = (u32)(Z.hi);	PUTU32(p+4,v);
 		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
 		v = (u32)(Z.lo);	PUTU32(p+12,v);
 #endif
 	}
 	else {
 		Xi[0] = Z.hi;
 		Xi[1] = Z.lo;
 	}
 }
 #define GCM_MUL(ctx,Xi)	  gcm_gmult_1bit(ctx->Xi.u,ctx->H.u)
 
 #endif
 
 #if	TABLE_BITS==4 && defined(GHASH_ASM)
 # if	!defined(I386_ONLY) && \
 	(defined(__i386)	|| defined(__i386__)	|| \
 	 defined(__x86_64)	|| defined(__x86_64__)	|| \
 	 defined(_M_IX86)	|| defined(_M_AMD64)	|| defined(_M_X64))
 #  define GHASH_ASM_X86_OR_64
 #  define GCM_FUNCREF_4BIT
 extern unsigned int OPENSSL_ia32cap_P[2];
 
 void gcm_init_clmul(u128 Htable[16],const u64 Xi[2]);
 void gcm_gmult_clmul(u64 Xi[2],const u128 Htable[16]);
 void gcm_ghash_clmul(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
 
 #  if	defined(__i386) || defined(__i386__) || defined(_M_IX86)
 #   define GHASH_ASM_X86
 void gcm_gmult_4bit_mmx(u64 Xi[2],const u128 Htable[16]);
 void gcm_ghash_4bit_mmx(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
 
 void gcm_gmult_4bit_x86(u64 Xi[2],const u128 Htable[16]);
 void gcm_ghash_4bit_x86(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
 #  endif
 # elif defined(__arm__) || defined(__arm)
 #  include "arm_arch.h"
 #  if __ARM_ARCH__>=7
 #   define GHASH_ASM_ARM
 #   define GCM_FUNCREF_4BIT
 void gcm_gmult_neon(u64 Xi[2],const u128 Htable[16]);
 void gcm_ghash_neon(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
 #  endif
 # endif
 #endif
 
 #ifdef GCM_FUNCREF_4BIT
 # undef  GCM_MUL
 # define GCM_MUL(ctx,Xi)	(*gcm_gmult_p)(ctx->Xi.u,ctx->Htable)
 # ifdef GHASH
 #  undef  GHASH
 #  define GHASH(ctx,in,len)	(*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len)
 # endif
 #endif
 
 void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx,void *key,block128_f block)
 {
 	const union { long one; char little; } is_endian = {1};
 
 	memset(ctx,0,sizeof(*ctx));
 	ctx->block = block;
 	ctx->key   = key;
 
 	(*block)(ctx->H.c,ctx->H.c,key);
 
 	if (is_endian.little) {
 		/* H is stored in host byte order */
 #ifdef BSWAP8
 		ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
 		ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
 #else
 		u8 *p = ctx->H.c;
 		u64 hi,lo;
 		hi = (u64)GETU32(p)  <<32|GETU32(p+4);
 		lo = (u64)GETU32(p+8)<<32|GETU32(p+12);
 		ctx->H.u[0] = hi;
 		ctx->H.u[1] = lo;
 #endif
 	}
 
 #if	TABLE_BITS==8
 	gcm_init_8bit(ctx->Htable,ctx->H.u);
 #elif	TABLE_BITS==4
 # if	defined(GHASH_ASM_X86_OR_64)
 #  if	!defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
 	if (OPENSSL_ia32cap_P[0]&(1<<24) &&	/* check FXSR bit */
 	    OPENSSL_ia32cap_P[1]&(1<<1) ) {	/* check PCLMULQDQ bit */
 		gcm_init_clmul(ctx->Htable,ctx->H.u);
 		ctx->gmult = gcm_gmult_clmul;
 		ctx->ghash = gcm_ghash_clmul;
 		return;
 	}
 #  endif
 	gcm_init_4bit(ctx->Htable,ctx->H.u);
 #  if	defined(GHASH_ASM_X86)			/* x86 only */
 #   if	defined(OPENSSL_IA32_SSE2)
 	if (OPENSSL_ia32cap_P[0]&(1<<25)) {	/* check SSE bit */
 #   else
 	if (OPENSSL_ia32cap_P[0]&(1<<23)) {	/* check MMX bit */
 #   endif
 		ctx->gmult = gcm_gmult_4bit_mmx;
 		ctx->ghash = gcm_ghash_4bit_mmx;
 	} else {
 		ctx->gmult = gcm_gmult_4bit_x86;
 		ctx->ghash = gcm_ghash_4bit_x86;
 	}
 #  else
 	ctx->gmult = gcm_gmult_4bit;
 	ctx->ghash = gcm_ghash_4bit;
 #  endif
 # elif	defined(GHASH_ASM_ARM)
 	if (OPENSSL_armcap_P & ARMV7_NEON) {
 		ctx->gmult = gcm_gmult_neon;
 		ctx->ghash = gcm_ghash_neon;
 	} else {
 		gcm_init_4bit(ctx->Htable,ctx->H.u);
 		ctx->gmult = gcm_gmult_4bit;
 		ctx->ghash = gcm_ghash_4bit;
 	}
 # else
 	gcm_init_4bit(ctx->Htable,ctx->H.u);
 # endif
 #endif
 }
 
 void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len)
 {
 	const union { long one; char little; } is_endian = {1};
 	unsigned int ctr;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 #endif
 
 	ctx->Yi.u[0]  = 0;
 	ctx->Yi.u[1]  = 0;
 	ctx->Xi.u[0]  = 0;
 	ctx->Xi.u[1]  = 0;
 	ctx->len.u[0] = 0;	/* AAD length */
 	ctx->len.u[1] = 0;	/* message length */
 	ctx->ares = 0;
 	ctx->mres = 0;
 
 	if (len==12) {
 		memcpy(ctx->Yi.c,iv,12);
 		ctx->Yi.c[15]=1;
 		ctr=1;
 	}
 	else {
 		size_t i;
 		u64 len0 = len;
 
 		while (len>=16) {
 			for (i=0; i<16; ++i) ctx->Yi.c[i] ^= iv[i];
 			GCM_MUL(ctx,Yi);
 			iv += 16;
 			len -= 16;
 		}
 		if (len) {
 			for (i=0; iYi.c[i] ^= iv[i];
 			GCM_MUL(ctx,Yi);
 		}
 		len0 <<= 3;
 		if (is_endian.little) {
 #ifdef BSWAP8
 			ctx->Yi.u[1]  ^= BSWAP8(len0);
 #else
 			ctx->Yi.c[8]  ^= (u8)(len0>>56);
 			ctx->Yi.c[9]  ^= (u8)(len0>>48);
 			ctx->Yi.c[10] ^= (u8)(len0>>40);
 			ctx->Yi.c[11] ^= (u8)(len0>>32);
 			ctx->Yi.c[12] ^= (u8)(len0>>24);
 			ctx->Yi.c[13] ^= (u8)(len0>>16);
 			ctx->Yi.c[14] ^= (u8)(len0>>8);
 			ctx->Yi.c[15] ^= (u8)(len0);
 #endif
 		}
 		else
 			ctx->Yi.u[1]  ^= len0;
 
 		GCM_MUL(ctx,Yi);
 
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctr = BSWAP4(ctx->Yi.d[3]);
 #else
 			ctr = GETU32(ctx->Yi.c+12);
 #endif
 		else
 			ctr = ctx->Yi.d[3];
 	}
 
 	(*ctx->block)(ctx->Yi.c,ctx->EK0.c,ctx->key);
 	++ctr;
 	if (is_endian.little)
 #ifdef BSWAP4
 		ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 		PUTU32(ctx->Yi.c+12,ctr);
 #endif
 	else
 		ctx->Yi.d[3] = ctr;
 }
 
 int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx,const unsigned char *aad,size_t len)
 {
 	size_t i;
 	unsigned int n;
 	u64 alen = ctx->len.u[0];
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 # ifdef GHASH
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx->ghash;
 # endif
 #endif
 
 	if (ctx->len.u[1]) return -2;
 
 	alen += len;
 	if (alen>(U64(1)<<61) || (sizeof(len)==8 && alenlen.u[0] = alen;
 
 	n = ctx->ares;
 	if (n) {
 		while (n && len) {
 			ctx->Xi.c[n] ^= *(aad++);
 			--len;
 			n = (n+1)%16;
 		}
 		if (n==0) GCM_MUL(ctx,Xi);
 		else {
 			ctx->ares = n;
 			return 0;
 		}
 	}
 
 #ifdef GHASH
 	if ((i = (len&(size_t)-16))) {
 		GHASH(ctx,aad,i);
 		aad += i;
 		len -= i;
 	}
 #else
 	while (len>=16) {
 		for (i=0; i<16; ++i) ctx->Xi.c[i] ^= aad[i];
 		GCM_MUL(ctx,Xi);
 		aad += 16;
 		len -= 16;
 	}
 #endif
 	if (len) {
 		n = (unsigned int)len;
 		for (i=0; iXi.c[i] ^= aad[i];
 	}
 
 	ctx->ares = n;
 	return 0;
 }
 
 int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 		const unsigned char *in, unsigned char *out,
 		size_t len)
 {
 	const union { long one; char little; } is_endian = {1};
 	unsigned int n, ctr;
 	size_t i;
 	u64        mlen  = ctx->len.u[1];
 	block128_f block = ctx->block;
 	void      *key   = ctx->key;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 # ifdef GHASH
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx->ghash;
 # endif
 #endif
 
 #if 0
 	n = (unsigned int)mlen%16; /* alternative to ctx->mres */
 #endif
 	mlen += len;
 	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen;
 
 	if (ctx->ares) {
 		/* First call to encrypt finalizes GHASH(AAD) */
 		GCM_MUL(ctx,Xi);
 		ctx->ares = 0;
 	}
 
 	if (is_endian.little)
 #ifdef BSWAP4
 		ctr = BSWAP4(ctx->Yi.d[3]);
 #else
 		ctr = GETU32(ctx->Yi.c+12);
 #endif
 	else
 		ctr = ctx->Yi.d[3];
 
 	n = ctx->mres;
 #if !defined(OPENSSL_SMALL_FOOTPRINT)
 	if (16%sizeof(size_t) == 0) do {	/* always true actually */
 		if (n) {
 			while (n && len) {
 				ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
 				--len;
 				n = (n+1)%16;
 			}
 			if (n==0) GCM_MUL(ctx,Xi);
 			else {
 				ctx->mres = n;
 				return 0;
 			}
 		}
 #if defined(STRICT_ALIGNMENT)
 		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
 			break;
 #endif
 #if defined(GHASH) && defined(GHASH_CHUNK)
 		while (len>=GHASH_CHUNK) {
 		    size_t j=GHASH_CHUNK;
 
 		    while (j) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
 				out_t[i] = in_t[i] ^ ctx->EKi.t[i];
 			out += 16;
 			in  += 16;
 			j   -= 16;
 		    }
 		    GHASH(ctx,out-GHASH_CHUNK,GHASH_CHUNK);
 		    len -= GHASH_CHUNK;
 		}
 		if ((i = (len&(size_t)-16))) {
 		    size_t j=i;
 
 		    while (len>=16) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
 				out_t[i] = in_t[i] ^ ctx->EKi.t[i];
 			out += 16;
 			in  += 16;
 			len -= 16;
 		    }
 		    GHASH(ctx,out-j,j);
 		}
 #else
 		while (len>=16) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
 				ctx->Xi.t[i] ^=
 				out_t[i] = in_t[i]^ctx->EKi.t[i];
 			GCM_MUL(ctx,Xi);
 			out += 16;
 			in  += 16;
 			len -= 16;
 		}
 #endif
 		if (len) {
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			while (len--) {
 				ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
 				++n;
 			}
 		}
 
 		ctx->mres = n;
 		return 0;
 	} while(0);
 #endif
 	for (i=0;iYi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 		}
 		ctx->Xi.c[n] ^= out[i] = in[i]^ctx->EKi.c[n];
 		n = (n+1)%16;
 		if (n==0)
 			GCM_MUL(ctx,Xi);
 	}
 
 	ctx->mres = n;
 	return 0;
 }
 
 int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 		const unsigned char *in, unsigned char *out,
 		size_t len)
 {
 	const union { long one; char little; } is_endian = {1};
 	unsigned int n, ctr;
 	size_t i;
 	u64        mlen  = ctx->len.u[1];
 	block128_f block = ctx->block;
 	void      *key   = ctx->key;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 # ifdef GHASH
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx->ghash;
 # endif
 #endif
 
 	mlen += len;
 	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen;
 
 	if (ctx->ares) {
 		/* First call to decrypt finalizes GHASH(AAD) */
 		GCM_MUL(ctx,Xi);
 		ctx->ares = 0;
 	}
 
 	if (is_endian.little)
 #ifdef BSWAP4
 		ctr = BSWAP4(ctx->Yi.d[3]);
 #else
 		ctr = GETU32(ctx->Yi.c+12);
 #endif
 	else
 		ctr = ctx->Yi.d[3];
 
 	n = ctx->mres;
 #if !defined(OPENSSL_SMALL_FOOTPRINT)
 	if (16%sizeof(size_t) == 0) do {	/* always true actually */
 		if (n) {
 			while (n && len) {
 				u8 c = *(in++);
 				*(out++) = c^ctx->EKi.c[n];
 				ctx->Xi.c[n] ^= c;
 				--len;
 				n = (n+1)%16;
 			}
 			if (n==0) GCM_MUL (ctx,Xi);
 			else {
 				ctx->mres = n;
 				return 0;
 			}
 		}
 #if defined(STRICT_ALIGNMENT)
 		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
 			break;
 #endif
 #if defined(GHASH) && defined(GHASH_CHUNK)
 		while (len>=GHASH_CHUNK) {
 		    size_t j=GHASH_CHUNK;
 
 		    GHASH(ctx,in,GHASH_CHUNK);
 		    while (j) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
 				out_t[i] = in_t[i]^ctx->EKi.t[i];
 			out += 16;
 			in  += 16;
 			j   -= 16;
 		    }
 		    len -= GHASH_CHUNK;
 		}
 		if ((i = (len&(size_t)-16))) {
 		    GHASH(ctx,in,i);
 		    while (len>=16) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
 				out_t[i] = in_t[i]^ctx->EKi.t[i];
 			out += 16;
 			in  += 16;
 			len -= 16;
 		    }
 		}
 #else
 		while (len>=16) {
 		    	size_t *out_t=(size_t *)out;
 		    	const size_t *in_t=(const size_t *)in;
 
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i) {
 				size_t c = in[i];
 				out[i] = c^ctx->EKi.t[i];
 				ctx->Xi.t[i] ^= c;
 			}
 			GCM_MUL(ctx,Xi);
 			out += 16;
 			in  += 16;
 			len -= 16;
 		}
 #endif
 		if (len) {
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 			while (len--) {
 				u8 c = in[n];
 				ctx->Xi.c[n] ^= c;
 				out[n] = c^ctx->EKi.c[n];
 				++n;
 			}
 		}
 
 		ctx->mres = n;
 		return 0;
 	} while(0);
 #endif
 	for (i=0;iYi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
 #ifdef BSWAP4
 				ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 				PUTU32(ctx->Yi.c+12,ctr);
 #endif
 			else
 				ctx->Yi.d[3] = ctr;
 		}
 		c = in[i];
 		out[i] = c^ctx->EKi.c[n];
 		ctx->Xi.c[n] ^= c;
 		n = (n+1)%16;
 		if (n==0)
 			GCM_MUL(ctx,Xi);
 	}
 
 	ctx->mres = n;
 	return 0;
 }
 
 int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
 		const unsigned char *in, unsigned char *out,
 		size_t len, ctr128_f stream)
 {
 	const union { long one; char little; } is_endian = {1};
 	unsigned int n, ctr;
 	size_t i;
 	u64   mlen = ctx->len.u[1];
 	void *key  = ctx->key;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 # ifdef GHASH
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx->ghash;
 # endif
 #endif
 
 	mlen += len;
 	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen;
 
 	if (ctx->ares) {
 		/* First call to encrypt finalizes GHASH(AAD) */
 		GCM_MUL(ctx,Xi);
 		ctx->ares = 0;
 	}
 
 	if (is_endian.little)
 #ifdef BSWAP4
 		ctr = BSWAP4(ctx->Yi.d[3]);
 #else
 		ctr = GETU32(ctx->Yi.c+12);
 #endif
 	else
 		ctr = ctx->Yi.d[3];
 
 	n = ctx->mres;
 	if (n) {
 		while (n && len) {
 			ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
 			--len;
 			n = (n+1)%16;
 		}
 		if (n==0) GCM_MUL(ctx,Xi);
 		else {
 			ctx->mres = n;
 			return 0;
 		}
 	}
 #if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
 	while (len>=GHASH_CHUNK) {
 		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
 		ctr += GHASH_CHUNK/16;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		GHASH(ctx,out,GHASH_CHUNK);
 		out += GHASH_CHUNK;
 		in  += GHASH_CHUNK;
 		len -= GHASH_CHUNK;
 	}
 #endif
 	if ((i = (len&(size_t)-16))) {
 		size_t j=i/16;
 
 		(*stream)(in,out,j,key,ctx->Yi.c);
 		ctr += (unsigned int)j;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		in  += i;
 		len -= i;
 #if defined(GHASH)
 		GHASH(ctx,out,i);
 		out += i;
 #else
 		while (j--) {
 			for (i=0;i<16;++i) ctx->Xi.c[i] ^= out[i];
 			GCM_MUL(ctx,Xi);
 			out += 16;
 		}
 #endif
 	}
 	if (len) {
 		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
 		++ctr;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		while (len--) {
 			ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
 			++n;
 		}
 	}
 
 	ctx->mres = n;
 	return 0;
 }
 
 int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
 		const unsigned char *in, unsigned char *out,
 		size_t len,ctr128_f stream)
 {
 	const union { long one; char little; } is_endian = {1};
 	unsigned int n, ctr;
 	size_t i;
 	u64   mlen = ctx->len.u[1];
 	void *key  = ctx->key;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 # ifdef GHASH
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx->ghash;
 # endif
 #endif
 
 	mlen += len;
 	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlenlen.u[1] = mlen;
 
 	if (ctx->ares) {
 		/* First call to decrypt finalizes GHASH(AAD) */
 		GCM_MUL(ctx,Xi);
 		ctx->ares = 0;
 	}
 
 	if (is_endian.little)
 #ifdef BSWAP4
 		ctr = BSWAP4(ctx->Yi.d[3]);
 #else
 		ctr = GETU32(ctx->Yi.c+12);
 #endif
 	else
 		ctr = ctx->Yi.d[3];
 
 	n = ctx->mres;
 	if (n) {
 		while (n && len) {
 			u8 c = *(in++);
 			*(out++) = c^ctx->EKi.c[n];
 			ctx->Xi.c[n] ^= c;
 			--len;
 			n = (n+1)%16;
 		}
 		if (n==0) GCM_MUL (ctx,Xi);
 		else {
 			ctx->mres = n;
 			return 0;
 		}
 	}
 #if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
 	while (len>=GHASH_CHUNK) {
 		GHASH(ctx,in,GHASH_CHUNK);
 		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
 		ctr += GHASH_CHUNK/16;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		out += GHASH_CHUNK;
 		in  += GHASH_CHUNK;
 		len -= GHASH_CHUNK;
 	}
 #endif
 	if ((i = (len&(size_t)-16))) {
 		size_t j=i/16;
 
 #if defined(GHASH)
 		GHASH(ctx,in,i);
 #else
 		while (j--) {
 			size_t k;
 			for (k=0;k<16;++k) ctx->Xi.c[k] ^= in[k];
 			GCM_MUL(ctx,Xi);
 			in += 16;
 		}
 		j   = i/16;
 		in -= i;
 #endif
 		(*stream)(in,out,j,key,ctx->Yi.c);
 		ctr += (unsigned int)j;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		out += i;
 		in  += i;
 		len -= i;
 	}
 	if (len) {
 		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
 		++ctr;
 		if (is_endian.little)
 #ifdef BSWAP4
 			ctx->Yi.d[3] = BSWAP4(ctr);
 #else
 			PUTU32(ctx->Yi.c+12,ctr);
 #endif
 		else
 			ctx->Yi.d[3] = ctr;
 		while (len--) {
 			u8 c = in[n];
 			ctx->Xi.c[n] ^= c;
 			out[n] = c^ctx->EKi.c[n];
 			++n;
 		}
 	}
 
 	ctx->mres = n;
 	return 0;
 }
 
 int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag,
 			size_t len)
 {
 	const union { long one; char little; } is_endian = {1};
 	u64 alen = ctx->len.u[0]<<3;
 	u64 clen = ctx->len.u[1]<<3;
 #ifdef GCM_FUNCREF_4BIT
 	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
 #endif
 
 	if (ctx->mres || ctx->ares)
 		GCM_MUL(ctx,Xi);
 
 	if (is_endian.little) {
 #ifdef BSWAP8
 		alen = BSWAP8(alen);
 		clen = BSWAP8(clen);
 #else
 		u8 *p = ctx->len.c;
 
 		ctx->len.u[0] = alen;
 		ctx->len.u[1] = clen;
 
 		alen = (u64)GETU32(p)  <<32|GETU32(p+4);
 		clen = (u64)GETU32(p+8)<<32|GETU32(p+12);
 #endif
 	}
 
 	ctx->Xi.u[0] ^= alen;
 	ctx->Xi.u[1] ^= clen;
 	GCM_MUL(ctx,Xi);
 
 	ctx->Xi.u[0] ^= ctx->EK0.u[0];
 	ctx->Xi.u[1] ^= ctx->EK0.u[1];
 
 	if (tag && len<=sizeof(ctx->Xi))
-		return memcmp(ctx->Xi.c,tag,len);
+		return CRYPTO_memcmp(ctx->Xi.c, tag, len);
 	else
 		return -1;
 }
 
 void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
 {
 	CRYPTO_gcm128_finish(ctx, NULL, 0);
 	memcpy(tag, ctx->Xi.c, len<=sizeof(ctx->Xi.c)?len:sizeof(ctx->Xi.c));
 }
 
 GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block)
 {
 	GCM128_CONTEXT *ret;
 
 	if ((ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT))))
 		CRYPTO_gcm128_init(ret,key,block);
 
 	return ret;
 }
 
 void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx)
 {
 	if (ctx) {
 		OPENSSL_cleanse(ctx,sizeof(*ctx));
 		OPENSSL_free(ctx);
 	}
 }
 
 #if defined(SELFTEST)
 #include 
 #include 
 
 /* Test Case 1 */
 static const u8	K1[16],
 		*P1=NULL,
 		*A1=NULL,
 		IV1[12],
 		*C1=NULL,
 		T1[]=  {0x58,0xe2,0xfc,0xce,0xfa,0x7e,0x30,0x61,0x36,0x7f,0x1d,0x57,0xa4,0xe7,0x45,0x5a};
 
 /* Test Case 2 */
 #define K2 K1
 #define A2 A1
 #define IV2 IV1
 static const u8	P2[16],
 		C2[]=  {0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78},
 		T2[]=  {0xab,0x6e,0x47,0xd4,0x2c,0xec,0x13,0xbd,0xf5,0x3a,0x67,0xb2,0x12,0x57,0xbd,0xdf};
 
 /* Test Case 3 */
 #define A3 A2
 static const u8	K3[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
 		P3[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
 		IV3[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
 		C3[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
 			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
 			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
 			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91,0x47,0x3f,0x59,0x85},
 		T3[]=  {0x4d,0x5c,0x2a,0xf3,0x27,0xcd,0x64,0xa6,0x2c,0xf3,0x5a,0xbd,0x2b,0xa6,0xfa,0xb4};
 
 /* Test Case 4 */
 #define K4 K3
 #define IV4 IV3
 static const u8	P4[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
 		A4[]=  {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
 			0xab,0xad,0xda,0xd2},
 		C4[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
 			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
 			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
 			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91},
 		T4[]=  {0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb,0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47};
 
 /* Test Case 5 */
 #define K5 K4
 #define P5 P4
 #define A5 A4
 static const u8	IV5[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
 		C5[]=  {0x61,0x35,0x3b,0x4c,0x28,0x06,0x93,0x4a,0x77,0x7f,0xf5,0x1f,0xa2,0x2a,0x47,0x55,
 			0x69,0x9b,0x2a,0x71,0x4f,0xcd,0xc6,0xf8,0x37,0x66,0xe5,0xf9,0x7b,0x6c,0x74,0x23,
 			0x73,0x80,0x69,0x00,0xe4,0x9f,0x24,0xb2,0x2b,0x09,0x75,0x44,0xd4,0x89,0x6b,0x42,
 			0x49,0x89,0xb5,0xe1,0xeb,0xac,0x0f,0x07,0xc2,0x3f,0x45,0x98},
 		T5[]=  {0x36,0x12,0xd2,0xe7,0x9e,0x3b,0x07,0x85,0x56,0x1b,0xe1,0x4a,0xac,0xa2,0xfc,0xcb};
 
 /* Test Case 6 */
 #define K6 K5
 #define P6 P5
 #define A6 A5
 static const u8	IV6[]= {0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
 			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
 			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
 			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
 		C6[]=  {0x8c,0xe2,0x49,0x98,0x62,0x56,0x15,0xb6,0x03,0xa0,0x33,0xac,0xa1,0x3f,0xb8,0x94,
 			0xbe,0x91,0x12,0xa5,0xc3,0xa2,0x11,0xa8,0xba,0x26,0x2a,0x3c,0xca,0x7e,0x2c,0xa7,
 			0x01,0xe4,0xa9,0xa4,0xfb,0xa4,0x3c,0x90,0xcc,0xdc,0xb2,0x81,0xd4,0x8c,0x7c,0x6f,
 			0xd6,0x28,0x75,0xd2,0xac,0xa4,0x17,0x03,0x4c,0x34,0xae,0xe5},
 		T6[]=  {0x61,0x9c,0xc5,0xae,0xff,0xfe,0x0b,0xfa,0x46,0x2a,0xf4,0x3c,0x16,0x99,0xd0,0x50};
 
 /* Test Case 7 */
 static const u8 K7[24],
 		*P7=NULL,
 		*A7=NULL,
 		IV7[12],
 		*C7=NULL,
 		T7[]=  {0xcd,0x33,0xb2,0x8a,0xc7,0x73,0xf7,0x4b,0xa0,0x0e,0xd1,0xf3,0x12,0x57,0x24,0x35};
 
 /* Test Case 8 */
 #define K8 K7
 #define IV8 IV7
 #define A8 A7
 static const u8	P8[16],
 		C8[]=  {0x98,0xe7,0x24,0x7c,0x07,0xf0,0xfe,0x41,0x1c,0x26,0x7e,0x43,0x84,0xb0,0xf6,0x00},
 		T8[]=  {0x2f,0xf5,0x8d,0x80,0x03,0x39,0x27,0xab,0x8e,0xf4,0xd4,0x58,0x75,0x14,0xf0,0xfb};
 
 /* Test Case 9 */
 #define A9 A8
 static const u8	K9[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
 			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c},
 		P9[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
 		IV9[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
 		C9[]=  {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
 			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
 			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
 			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10,0xac,0xad,0xe2,0x56},
 		T9[]=  {0x99,0x24,0xa7,0xc8,0x58,0x73,0x36,0xbf,0xb1,0x18,0x02,0x4d,0xb8,0x67,0x4a,0x14};
 
 /* Test Case 10 */
 #define K10 K9
 #define IV10 IV9
 static const u8	P10[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
 		A10[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
 			0xab,0xad,0xda,0xd2},
 		C10[]= {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
 			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
 			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
 			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10},
 		T10[]= {0x25,0x19,0x49,0x8e,0x80,0xf1,0x47,0x8f,0x37,0xba,0x55,0xbd,0x6d,0x27,0x61,0x8c};
 
 /* Test Case 11 */
 #define K11 K10
 #define P11 P10
 #define A11 A10
 static const u8	IV11[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
 		C11[]= {0x0f,0x10,0xf5,0x99,0xae,0x14,0xa1,0x54,0xed,0x24,0xb3,0x6e,0x25,0x32,0x4d,0xb8,
 			0xc5,0x66,0x63,0x2e,0xf2,0xbb,0xb3,0x4f,0x83,0x47,0x28,0x0f,0xc4,0x50,0x70,0x57,
 			0xfd,0xdc,0x29,0xdf,0x9a,0x47,0x1f,0x75,0xc6,0x65,0x41,0xd4,0xd4,0xda,0xd1,0xc9,
 			0xe9,0x3a,0x19,0xa5,0x8e,0x8b,0x47,0x3f,0xa0,0xf0,0x62,0xf7},
 		T11[]= {0x65,0xdc,0xc5,0x7f,0xcf,0x62,0x3a,0x24,0x09,0x4f,0xcc,0xa4,0x0d,0x35,0x33,0xf8};
 
 /* Test Case 12 */
 #define K12 K11
 #define P12 P11
 #define A12 A11
 static const u8	IV12[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
 			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
 			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
 			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
 		C12[]= {0xd2,0x7e,0x88,0x68,0x1c,0xe3,0x24,0x3c,0x48,0x30,0x16,0x5a,0x8f,0xdc,0xf9,0xff,
 			0x1d,0xe9,0xa1,0xd8,0xe6,0xb4,0x47,0xef,0x6e,0xf7,0xb7,0x98,0x28,0x66,0x6e,0x45,
 			0x81,0xe7,0x90,0x12,0xaf,0x34,0xdd,0xd9,0xe2,0xf0,0x37,0x58,0x9b,0x29,0x2d,0xb3,
 			0xe6,0x7c,0x03,0x67,0x45,0xfa,0x22,0xe7,0xe9,0xb7,0x37,0x3b},
 		T12[]= {0xdc,0xf5,0x66,0xff,0x29,0x1c,0x25,0xbb,0xb8,0x56,0x8f,0xc3,0xd3,0x76,0xa6,0xd9};
 
 /* Test Case 13 */
 static const u8	K13[32],
 		*P13=NULL,
 		*A13=NULL,
 		IV13[12],
 		*C13=NULL,
 		T13[]={0x53,0x0f,0x8a,0xfb,0xc7,0x45,0x36,0xb9,0xa9,0x63,0xb4,0xf1,0xc4,0xcb,0x73,0x8b};
 
 /* Test Case 14 */
 #define K14 K13
 #define A14 A13
 static const u8	P14[16],
 		IV14[12],
 		C14[]= {0xce,0xa7,0x40,0x3d,0x4d,0x60,0x6b,0x6e,0x07,0x4e,0xc5,0xd3,0xba,0xf3,0x9d,0x18},
 		T14[]= {0xd0,0xd1,0xc8,0xa7,0x99,0x99,0x6b,0xf0,0x26,0x5b,0x98,0xb5,0xd4,0x8a,0xb9,0x19};
 
 /* Test Case 15 */
 #define A15 A14
 static const u8	K15[]= {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
 			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
 		P15[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
 		IV15[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
 		C15[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
 			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
 			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
 			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62,0x89,0x80,0x15,0xad},
 		T15[]= {0xb0,0x94,0xda,0xc5,0xd9,0x34,0x71,0xbd,0xec,0x1a,0x50,0x22,0x70,0xe3,0xcc,0x6c};
 
 /* Test Case 16 */
 #define K16 K15
 #define IV16 IV15
 static const u8	P16[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
 		A16[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
 			0xab,0xad,0xda,0xd2},
 		C16[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
 			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
 			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
 			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62},
 		T16[]= {0x76,0xfc,0x6e,0xce,0x0f,0x4e,0x17,0x68,0xcd,0xdf,0x88,0x53,0xbb,0x2d,0x55,0x1b};
 
 /* Test Case 17 */
 #define K17 K16
 #define P17 P16
 #define A17 A16
 static const u8	IV17[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
 		C17[]= {0xc3,0x76,0x2d,0xf1,0xca,0x78,0x7d,0x32,0xae,0x47,0xc1,0x3b,0xf1,0x98,0x44,0xcb,
 			0xaf,0x1a,0xe1,0x4d,0x0b,0x97,0x6a,0xfa,0xc5,0x2f,0xf7,0xd7,0x9b,0xba,0x9d,0xe0,
 			0xfe,0xb5,0x82,0xd3,0x39,0x34,0xa4,0xf0,0x95,0x4c,0xc2,0x36,0x3b,0xc7,0x3f,0x78,
 			0x62,0xac,0x43,0x0e,0x64,0xab,0xe4,0x99,0xf4,0x7c,0x9b,0x1f},
 		T17[]= {0x3a,0x33,0x7d,0xbf,0x46,0xa7,0x92,0xc4,0x5e,0x45,0x49,0x13,0xfe,0x2e,0xa8,0xf2};
 
 /* Test Case 18 */
 #define K18 K17
 #define P18 P17
 #define A18 A17
 static const u8	IV18[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
 			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
 			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
 			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
 		C18[]= {0x5a,0x8d,0xef,0x2f,0x0c,0x9e,0x53,0xf1,0xf7,0x5d,0x78,0x53,0x65,0x9e,0x2a,0x20,
 			0xee,0xb2,0xb2,0x2a,0xaf,0xde,0x64,0x19,0xa0,0x58,0xab,0x4f,0x6f,0x74,0x6b,0xf4,
 			0x0f,0xc0,0xc3,0xb7,0x80,0xf2,0x44,0x45,0x2d,0xa3,0xeb,0xf1,0xc5,0xd8,0x2c,0xde,
 			0xa2,0x41,0x89,0x97,0x20,0x0e,0xf8,0x2e,0x44,0xae,0x7e,0x3f},
 		T18[]= {0xa4,0x4a,0x82,0x66,0xee,0x1c,0x8e,0xb0,0xc8,0xb5,0xd4,0xcf,0x5a,0xe9,0xf1,0x9a};
 
 /* Test Case 19 */
 #define K19 K1
 #define P19 P1
 #define IV19 IV1
 #define C19 C1
 static const u8 A19[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
 			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
 			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
 			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55,
 			0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
 			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
 			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
 			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62,0x89,0x80,0x15,0xad},
 		T19[]= {0x5f,0xea,0x79,0x3a,0x2d,0x6f,0x97,0x4d,0x37,0xe6,0x8e,0x0c,0xb8,0xff,0x94,0x92};
 
 /* Test Case 20 */
 #define K20 K1
 #define A20 A1
 static const u8 IV20[64]={0xff,0xff,0xff,0xff},	/* this results in 0xff in counter LSB */
 		P20[288],
 		C20[]= {0x56,0xb3,0x37,0x3c,0xa9,0xef,0x6e,0x4a,0x2b,0x64,0xfe,0x1e,0x9a,0x17,0xb6,0x14,
 			0x25,0xf1,0x0d,0x47,0xa7,0x5a,0x5f,0xce,0x13,0xef,0xc6,0xbc,0x78,0x4a,0xf2,0x4f,
 			0x41,0x41,0xbd,0xd4,0x8c,0xf7,0xc7,0x70,0x88,0x7a,0xfd,0x57,0x3c,0xca,0x54,0x18,
 			0xa9,0xae,0xff,0xcd,0x7c,0x5c,0xed,0xdf,0xc6,0xa7,0x83,0x97,0xb9,0xa8,0x5b,0x49,
 			0x9d,0xa5,0x58,0x25,0x72,0x67,0xca,0xab,0x2a,0xd0,0xb2,0x3c,0xa4,0x76,0xa5,0x3c,
 			0xb1,0x7f,0xb4,0x1c,0x4b,0x8b,0x47,0x5c,0xb4,0xf3,0xf7,0x16,0x50,0x94,0xc2,0x29,
 			0xc9,0xe8,0xc4,0xdc,0x0a,0x2a,0x5f,0xf1,0x90,0x3e,0x50,0x15,0x11,0x22,0x13,0x76,
 			0xa1,0xcd,0xb8,0x36,0x4c,0x50,0x61,0xa2,0x0c,0xae,0x74,0xbc,0x4a,0xcd,0x76,0xce,
 			0xb0,0xab,0xc9,0xfd,0x32,0x17,0xef,0x9f,0x8c,0x90,0xbe,0x40,0x2d,0xdf,0x6d,0x86,
 			0x97,0xf4,0xf8,0x80,0xdf,0xf1,0x5b,0xfb,0x7a,0x6b,0x28,0x24,0x1e,0xc8,0xfe,0x18,
 			0x3c,0x2d,0x59,0xe3,0xf9,0xdf,0xff,0x65,0x3c,0x71,0x26,0xf0,0xac,0xb9,0xe6,0x42,
 			0x11,0xf4,0x2b,0xae,0x12,0xaf,0x46,0x2b,0x10,0x70,0xbe,0xf1,0xab,0x5e,0x36,0x06,
 			0x87,0x2c,0xa1,0x0d,0xee,0x15,0xb3,0x24,0x9b,0x1a,0x1b,0x95,0x8f,0x23,0x13,0x4c,
 			0x4b,0xcc,0xb7,0xd0,0x32,0x00,0xbc,0xe4,0x20,0xa2,0xf8,0xeb,0x66,0xdc,0xf3,0x64,
 			0x4d,0x14,0x23,0xc1,0xb5,0x69,0x90,0x03,0xc1,0x3e,0xce,0xf4,0xbf,0x38,0xa3,0xb6,
 			0x0e,0xed,0xc3,0x40,0x33,0xba,0xc1,0x90,0x27,0x83,0xdc,0x6d,0x89,0xe2,0xe7,0x74,
 			0x18,0x8a,0x43,0x9c,0x7e,0xbc,0xc0,0x67,0x2d,0xbd,0xa4,0xdd,0xcf,0xb2,0x79,0x46,
 			0x13,0xb0,0xbe,0x41,0x31,0x5e,0xf7,0x78,0x70,0x8a,0x70,0xee,0x7d,0x75,0x16,0x5c},
 		T20[]= {0x8b,0x30,0x7f,0x6b,0x33,0x28,0x6d,0x0a,0xb0,0x26,0xa9,0xed,0x3f,0xe1,0xe8,0x5f};
 
 #define TEST_CASE(n)	do {					\
 	u8 out[sizeof(P##n)];					\
 	AES_set_encrypt_key(K##n,sizeof(K##n)*8,&key);		\
 	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);	\
 	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
 	memset(out,0,sizeof(out));				\
 	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
 	if (P##n) CRYPTO_gcm128_encrypt(&ctx,P##n,out,sizeof(out));	\
 	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
 	    (C##n && memcmp(out,C##n,sizeof(out))))		\
 		ret++, printf ("encrypt test#%d failed.\n",n);	\
 	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
 	memset(out,0,sizeof(out));				\
 	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
 	if (C##n) CRYPTO_gcm128_decrypt(&ctx,C##n,out,sizeof(out));	\
 	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
 	    (P##n && memcmp(out,P##n,sizeof(out))))		\
 		ret++, printf ("decrypt test#%d failed.\n",n);	\
 	} while(0)
 
 int main()
 {
 	GCM128_CONTEXT ctx;
 	AES_KEY key;
 	int ret=0;
 
 	TEST_CASE(1);
 	TEST_CASE(2);
 	TEST_CASE(3);
 	TEST_CASE(4);
 	TEST_CASE(5);
 	TEST_CASE(6);
 	TEST_CASE(7);
 	TEST_CASE(8);
 	TEST_CASE(9);
 	TEST_CASE(10);
 	TEST_CASE(11);
 	TEST_CASE(12);
 	TEST_CASE(13);
 	TEST_CASE(14);
 	TEST_CASE(15);
 	TEST_CASE(16);
 	TEST_CASE(17);
 	TEST_CASE(18);
 	TEST_CASE(19);
 	TEST_CASE(20);
 
 #ifdef OPENSSL_CPUID_OBJ
 	{
 	size_t start,stop,gcm_t,ctr_t,OPENSSL_rdtsc();
 	union { u64 u; u8 c[1024]; } buf;
 	int i;
 
 	AES_set_encrypt_key(K1,sizeof(K1)*8,&key);
 	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);
 	CRYPTO_gcm128_setiv(&ctx,IV1,sizeof(IV1));
 
 	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
 	start = OPENSSL_rdtsc();
 	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
 	gcm_t = OPENSSL_rdtsc() - start;
 
 	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
 			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
 			(block128_f)AES_encrypt);
 	start = OPENSSL_rdtsc();
 	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
 			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
 			(block128_f)AES_encrypt);
 	ctr_t = OPENSSL_rdtsc() - start;
 
 	printf("%.2f-%.2f=%.2f\n",
 			gcm_t/(double)sizeof(buf),
 			ctr_t/(double)sizeof(buf),
 			(gcm_t-ctr_t)/(double)sizeof(buf));
 #ifdef GHASH
 	{
 	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
 				const u8 *inp,size_t len)	= ctx.ghash;
 
 	GHASH((&ctx),buf.c,sizeof(buf));
 	start = OPENSSL_rdtsc();
 	for (i=0;i<100;++i) GHASH((&ctx),buf.c,sizeof(buf));
 	gcm_t = OPENSSL_rdtsc() - start;
 	printf("%.2f\n",gcm_t/(double)sizeof(buf)/(double)i);
 	}
 #endif
 	}
 #endif
 
 	return ret;
 }
 #endif
Index: releng/10.1/crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/objects/obj_dat.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/objects/obj_dat.c	(revision 284295)
@@ -1,812 +1,815 @@
 /* crypto/objects/obj_dat.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 
 /* obj_dat.h is generated from objects.h by obj_dat.pl */
 #ifndef OPENSSL_NO_OBJECT
 #include "obj_dat.h"
 #else
 /* You will have to load all the objects needed manually in the application */
 #define NUM_NID 0
 #define NUM_SN 0
 #define NUM_LN 0
 #define NUM_OBJ 0
 static const unsigned char lvalues[1];
 static const ASN1_OBJECT nid_objs[1];
 static const unsigned int sn_objs[1];
 static const unsigned int ln_objs[1];
 static const unsigned int obj_objs[1];
 #endif
 
 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
 
 #define ADDED_DATA	0
 #define ADDED_SNAME	1
 #define ADDED_LNAME	2
 #define ADDED_NID	3
 
 typedef struct added_obj_st
 	{
 	int type;
 	ASN1_OBJECT *obj;
 	} ADDED_OBJ;
 DECLARE_LHASH_OF(ADDED_OBJ);
 
 static int new_nid=NUM_NID;
 static LHASH_OF(ADDED_OBJ) *added=NULL;
 
 static int sn_cmp(const ASN1_OBJECT * const *a, const unsigned int *b)
 	{ return(strcmp((*a)->sn,nid_objs[*b].sn)); }
 
 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
 
 static int ln_cmp(const ASN1_OBJECT * const *a, const unsigned int *b)
 	{ return(strcmp((*a)->ln,nid_objs[*b].ln)); }
 
 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
 
 static unsigned long added_obj_hash(const ADDED_OBJ *ca)
 	{
 	const ASN1_OBJECT *a;
 	int i;
 	unsigned long ret=0;
 	unsigned char *p;
 
 	a=ca->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		ret=a->length<<20L;
 		p=(unsigned char *)a->data;
 		for (i=0; ilength; i++)
 			ret^=p[i]<<((i*3)%24);
 		break;
 	case ADDED_SNAME:
 		ret=lh_strhash(a->sn);
 		break;
 	case ADDED_LNAME:
 		ret=lh_strhash(a->ln);
 		break;
 	case ADDED_NID:
 		ret=a->nid;
 		break;
 	default:
 		/* abort(); */
 		return 0;
 		}
 	ret&=0x3fffffffL;
 	ret|=ca->type<<30L;
 	return(ret);
 	}
 static IMPLEMENT_LHASH_HASH_FN(added_obj, ADDED_OBJ)
 
 static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
 	{
 	ASN1_OBJECT *a,*b;
 	int i;
 
 	i=ca->type-cb->type;
 	if (i) return(i);
 	a=ca->obj;
 	b=cb->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		i=(a->length - b->length);
 		if (i) return(i);
 		return(memcmp(a->data,b->data,(size_t)a->length));
 	case ADDED_SNAME:
 		if (a->sn == NULL) return(-1);
 		else if (b->sn == NULL) return(1);
 		else return(strcmp(a->sn,b->sn));
 	case ADDED_LNAME:
 		if (a->ln == NULL) return(-1);
 		else if (b->ln == NULL) return(1);
 		else return(strcmp(a->ln,b->ln));
 	case ADDED_NID:
 		return(a->nid-b->nid);
 	default:
 		/* abort(); */
 		return 0;
 		}
 	}
 static IMPLEMENT_LHASH_COMP_FN(added_obj, ADDED_OBJ)
 
 static int init_added(void)
 	{
 	if (added != NULL) return(1);
 	added=lh_ADDED_OBJ_new();
 	return(added != NULL);
 	}
 
 static void cleanup1_doall(ADDED_OBJ *a)
 	{
 	a->obj->nid=0;
 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
 	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	}
 
 static void cleanup2_doall(ADDED_OBJ *a)
 	{ a->obj->nid++; }
 
 static void cleanup3_doall(ADDED_OBJ *a)
 	{
 	if (--a->obj->nid == 0)
 		ASN1_OBJECT_free(a->obj);
 	OPENSSL_free(a);
 	}
 
 static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ)
 
 /* The purpose of obj_cleanup_defer is to avoid EVP_cleanup() attempting
  * to use freed up OIDs. If neccessary the actual freeing up of OIDs is
  * delayed.
  */
 
 int obj_cleanup_defer = 0;
 
 void check_defer(int nid)
 	{
 	if (!obj_cleanup_defer && nid >= NUM_NID)
 			obj_cleanup_defer = 1;
 	}
 
 void OBJ_cleanup(void)
 	{
 	if (obj_cleanup_defer)
 		{
 		obj_cleanup_defer = 2;
 		return ;
 		}
 	if (added == NULL) return;
 	lh_ADDED_OBJ_down_load(added) = 0;
 	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
 	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
 	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
 	lh_ADDED_OBJ_free(added);
 	added=NULL;
 	}
 
 int OBJ_new_nid(int num)
 	{
 	int i;
 
 	i=new_nid;
 	new_nid+=num;
 	return(i);
 	}
 
 int OBJ_add_object(const ASN1_OBJECT *obj)
 	{
 	ASN1_OBJECT *o;
 	ADDED_OBJ *ao[4]={NULL,NULL,NULL,NULL},*aop;
 	int i;
 
 	if (added == NULL)
 		if (!init_added()) return(0);
 	if ((o=OBJ_dup(obj)) == NULL) goto err;
 	if (!(ao[ADDED_NID]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if ((o->length != 0) && (obj->data != NULL))
 		if (!(ao[ADDED_DATA]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->sn != NULL)
 		if (!(ao[ADDED_SNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->ln != NULL)
 		if (!(ao[ADDED_LNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		{
 		if (ao[i] != NULL)
 			{
 			ao[i]->type=i;
 			ao[i]->obj=o;
 			aop=lh_ADDED_OBJ_insert(added,ao[i]);
 			/* memory leak, buit should not normally matter */
 			if (aop != NULL)
 				OPENSSL_free(aop);
 			}
 		}
 	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA);
 
 	return(o->nid);
 err2:
 	OBJerr(OBJ_F_OBJ_ADD_OBJECT,ERR_R_MALLOC_FAILURE);
 err:
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		if (ao[i] != NULL) OPENSSL_free(ao[i]);
 	if (o != NULL) OPENSSL_free(o);
 	return(NID_undef);
 	}
 
 ASN1_OBJECT *OBJ_nid2obj(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return((ASN1_OBJECT *)&(nid_objs[n]));
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2sn(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].sn);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->sn);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2ln(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].ln);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->ln);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 static int obj_cmp(const ASN1_OBJECT * const *ap, const unsigned int *bp)
 	{
 	int j;
 	const ASN1_OBJECT *a= *ap;
 	const ASN1_OBJECT *b= &nid_objs[*bp];
 
 	j=(a->length - b->length);
         if (j) return(j);
 	return(memcmp(a->data,b->data,a->length));
 	}
 
 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
 
 int OBJ_obj2nid(const ASN1_OBJECT *a)
 	{
 	const unsigned int *op;
 	ADDED_OBJ ad,*adp;
 
 	if (a == NULL)
 		return(NID_undef);
 	if (a->nid != 0)
 		return(a->nid);
 
+	if (a->length == 0)
+		return NID_undef;
+
 	if (added != NULL)
 		{
 		ad.type=ADDED_DATA;
 		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
 	if (op == NULL)
 		return(NID_undef);
 	return(nid_objs[*op].nid);
 	}
 
 /* Convert an object name into an ASN1_OBJECT
  * if "noname" is not set then search for short and long names first.
  * This will convert the "dotted" form into an object: unlike OBJ_txt2nid
  * it can be used with any objects, not just registered ones.
  */
 
 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
 	{
 	int nid = NID_undef;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	unsigned char *p;
 	const unsigned char *cp;
 	int i, j;
 
 	if(!no_name) {
 		if( ((nid = OBJ_sn2nid(s)) != NID_undef) ||
 			((nid = OBJ_ln2nid(s)) != NID_undef) ) 
 					return OBJ_nid2obj(nid);
 	}
 
 	/* Work out size of content octets */
 	i=a2d_ASN1_OBJECT(NULL,0,s,-1);
 	if (i <= 0) {
 		/* Don't clear the error */
 		/*ERR_clear_error();*/
 		return NULL;
 	}
 	/* Work out total size */
 	j = ASN1_object_size(0,i,V_ASN1_OBJECT);
 
 	if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL;
 
 	p = buf;
 	/* Write out tag+length */
 	ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
 	/* Write out contents */
 	a2d_ASN1_OBJECT(p,i,s,-1);
 
 	cp=buf;
 	op=d2i_ASN1_OBJECT(NULL,&cp,j);
 	OPENSSL_free(buf);
 	return op;
 	}
 
 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
 {
 	int i,n=0,len,nid, first, use_bn;
 	BIGNUM *bl;
 	unsigned long l;
 	const unsigned char *p;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
 	/* Ensure that, at every state, |buf| is NUL-terminated. */
 	if (buf && buf_len > 0)
 		buf[0] = '\0';
 
 	if ((a == NULL) || (a->data == NULL))
 		return(0);
 
 	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
 		{
 		const char *s;
 		s=OBJ_nid2ln(nid);
 		if (s == NULL)
 			s=OBJ_nid2sn(nid);
 		if (s)
 			{
 			if (buf)
 				BUF_strlcpy(buf,s,buf_len);
 			n=strlen(s);
 			return n;
 			}
 		}
 
 
 	len=a->length;
 	p=a->data;
 
 	first = 1;
 	bl = NULL;
 
 	while (len > 0)
 		{
 		l=0;
 		use_bn = 0;
 		for (;;)
 			{
 			unsigned char c = *p++;
 			len--;
 			if ((len == 0) && (c & 0x80))
 				goto err;
 			if (use_bn)
 				{
 				if (!BN_add_word(bl, c & 0x7f))
 					goto err;
 				}
 			else
 				l |= c  & 0x7f;
 			if (!(c & 0x80))
 				break;
 			if (!use_bn && (l > (ULONG_MAX >> 7L)))
 				{
 				if (!bl && !(bl = BN_new()))
 					goto err;
 				if (!BN_set_word(bl, l))
 					goto err;
 				use_bn = 1;
 				}
 			if (use_bn)
 				{
 				if (!BN_lshift(bl, bl, 7))
 					goto err;
 				}
 			else
 				l<<=7L;
 			}
 
 		if (first)
 			{
 			first = 0;
 			if (l >= 80)
 				{
 				i = 2;
 				if (use_bn)
 					{
 					if (!BN_sub_word(bl, 80))
 						goto err;
 					}
 				else
 					l -= 80;
 				}
 			else
 				{
 				i=(int)(l/40);
 				l-=(long)(i*40);
 				}
 			if (buf && (buf_len > 1))
 				{
 				*buf++ = i + '0';
 				*buf = '\0';
 				buf_len--;
 				}
 			n++;
 			}
 
 		if (use_bn)
 			{
 			char *bndec;
 			bndec = BN_bn2dec(bl);
 			if (!bndec)
 				goto err;
 			i = strlen(bndec);
 			if (buf)
 				{
 				if (buf_len > 1)
 					{
 					*buf++ = '.';
 					*buf = '\0';
 					buf_len--;
 					}
 				BUF_strlcpy(buf,bndec,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n++;
 			n += i;
 			OPENSSL_free(bndec);
 			}
 		else
 			{
 			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
 			i=strlen(tbuf);
 			if (buf && (buf_len > 0))
 				{
 				BUF_strlcpy(buf,tbuf,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n+=i;
 			l=0;
 			}
 		}
 
 	if (bl)
 		BN_free(bl);
 	return n;
 
 	err:
 	if (bl)
 		BN_free(bl);
 	return -1;
 }
 
 int OBJ_txt2nid(const char *s)
 {
 	ASN1_OBJECT *obj;
 	int nid;
 	obj = OBJ_txt2obj(s, 0);
 	nid = OBJ_obj2nid(obj);
 	ASN1_OBJECT_free(obj);
 	return nid;
 }
 
 int OBJ_ln2nid(const char *s)
 	{
 	ASN1_OBJECT o;
 	const ASN1_OBJECT *oo= &o;
 	ADDED_OBJ ad,*adp;
 	const unsigned int *op;
 
 	o.ln=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_LNAME;
 		ad.obj= &o;
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
 	if (op == NULL) return(NID_undef);
 	return(nid_objs[*op].nid);
 	}
 
 int OBJ_sn2nid(const char *s)
 	{
 	ASN1_OBJECT o;
 	const ASN1_OBJECT *oo= &o;
 	ADDED_OBJ ad,*adp;
 	const unsigned int *op;
 
 	o.sn=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_SNAME;
 		ad.obj= &o;
 		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
 	if (op == NULL) return(NID_undef);
 	return(nid_objs[*op].nid);
 	}
 
 const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
 			 int (*cmp)(const void *, const void *))
 	{
 	return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
 	}
 
 const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
 			    int size,
 			    int (*cmp)(const void *, const void *),
 			    int flags)
 	{
 	const char *base=base_;
 	int l,h,i=0,c=0;
 	const char *p = NULL;
 
 	if (num == 0) return(NULL);
 	l=0;
 	h=num;
 	while (l < h)
 		{
 		i=(l+h)/2;
 		p= &(base[i*size]);
 		c=(*cmp)(key,p);
 		if (c < 0)
 			h=i;
 		else if (c > 0)
 			l=i+1;
 		else
 			break;
 		}
 #ifdef CHARSET_EBCDIC
 /* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and
  * I don't have perl (yet), we revert to a *LINEAR* search
  * when the object wasn't found in the binary search.
  */
 	if (c != 0)
 		{
 		for (i=0; i 0 && (*cmp)(key,&(base[(i-1)*size])) == 0)
 			i--;
 		p = &(base[i*size]);
 		}
 	return(p);
 	}
 
 int OBJ_create_objects(BIO *in)
 	{
 	MS_STATIC char buf[512];
 	int i,num=0;
 	char *o,*s,*l=NULL;
 
 	for (;;)
 		{
 		s=o=NULL;
 		i=BIO_gets(in,buf,512);
 		if (i <= 0) return(num);
 		buf[i-1]='\0';
 		if (!isalnum((unsigned char)buf[0])) return(num);
 		o=s=buf;
 		while (isdigit((unsigned char)*s) || (*s == '.'))
 			s++;
 		if (*s != '\0')
 			{
 			*(s++)='\0';
 			while (isspace((unsigned char)*s))
 				s++;
 			if (*s == '\0')
 				s=NULL;
 			else
 				{
 				l=s;
 				while ((*l != '\0') && !isspace((unsigned char)*l))
 					l++;
 				if (*l != '\0')
 					{
 					*(l++)='\0';
 					while (isspace((unsigned char)*l))
 						l++;
 					if (*l == '\0') l=NULL;
 					}
 				else
 					l=NULL;
 				}
 			}
 		else
 			s=NULL;
 		if ((o == NULL) || (*o == '\0')) return(num);
 		if (!OBJ_create(o,s,l)) return(num);
 		num++;
 		}
 	/* return(num); */
 	}
 
 int OBJ_create(const char *oid, const char *sn, const char *ln)
 	{
 	int ok=0;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	int i;
 
 	i=a2d_ASN1_OBJECT(NULL,0,oid,-1);
 	if (i <= 0) return(0);
 
 	if ((buf=(unsigned char *)OPENSSL_malloc(i)) == NULL)
 		{
 		OBJerr(OBJ_F_OBJ_CREATE,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	i=a2d_ASN1_OBJECT(buf,i,oid,-1);
 	if (i == 0)
 		goto err;
 	op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln);
 	if (op == NULL) 
 		goto err;
 	ok=OBJ_add_object(op);
 err:
 	ASN1_OBJECT_free(op);
 	OPENSSL_free(buf);
 	return(ok);
 	}
Index: releng/10.1/crypto/openssl/crypto/pkcs12/p12_mutl.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/pkcs12/p12_mutl.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/pkcs12/p12_mutl.c	(revision 284295)
@@ -1,190 +1,192 @@
 /* p12_mutl.c */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #ifndef OPENSSL_NO_HMAC
 #include 
 #include "cryptlib.h"
+#include 
 #include 
 #include 
 #include 
 
 /* Generate a MAC */
 int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
 		   unsigned char *mac, unsigned int *maclen)
 {
 	const EVP_MD *md_type;
 	HMAC_CTX hmac;
 	unsigned char key[EVP_MAX_MD_SIZE], *salt;
 	int saltlen, iter;
 	int md_size;
 
 	if (!PKCS7_type_is_data(p12->authsafes))
 		{
 		PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_CONTENT_TYPE_NOT_DATA);
 		return 0;
 		}
 
 	salt = p12->mac->salt->data;
 	saltlen = p12->mac->salt->length;
 	if (!p12->mac->iter) iter = 1;
 	else iter = ASN1_INTEGER_get (p12->mac->iter);
     	if(!(md_type =
 		 EVP_get_digestbyobj (p12->mac->dinfo->algor->algorithm))) {
 		PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
 		return 0;
 	}
 	md_size = EVP_MD_size(md_type);
 	if (md_size < 0)
 	    return 0;
 	if(!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
 				 md_size, key, md_type)) {
 		PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_KEY_GEN_ERROR);
 		return 0;
 	}
 	HMAC_CTX_init(&hmac);
 	if (!HMAC_Init_ex(&hmac, key, md_size, md_type, NULL)
     		|| !HMAC_Update(&hmac, p12->authsafes->d.data->data,
 					 p12->authsafes->d.data->length)
     		|| !HMAC_Final(&hmac, mac, maclen))
 		{
     		HMAC_CTX_cleanup(&hmac);
 		return 0;
 		}
     	HMAC_CTX_cleanup(&hmac);
 	return 1;
 }
 
 /* Verify the mac */
 int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
 {
 	unsigned char mac[EVP_MAX_MD_SIZE];
 	unsigned int maclen;
 	if(p12->mac == NULL) {
 		PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC,PKCS12_R_MAC_ABSENT);
 		return 0;
 	}
 	if (!PKCS12_gen_mac (p12, pass, passlen, mac, &maclen)) {
 		PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC,PKCS12_R_MAC_GENERATION_ERROR);
 		return 0;
 	}
 	if ((maclen != (unsigned int)p12->mac->dinfo->digest->length)
-	|| memcmp (mac, p12->mac->dinfo->digest->data, maclen)) return 0;
+        || CRYPTO_memcmp(mac, p12->mac->dinfo->digest->data, maclen))
+		return 0;
 	return 1;
 }
 
 /* Set a mac */
 
 int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
 	     unsigned char *salt, int saltlen, int iter, const EVP_MD *md_type)
 {
 	unsigned char mac[EVP_MAX_MD_SIZE];
 	unsigned int maclen;
 
 	if (!md_type) md_type = EVP_sha1();
 	if (PKCS12_setup_mac (p12, iter, salt, saltlen, md_type) ==
 				 	PKCS12_ERROR) {
 		PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_SETUP_ERROR);
 		return 0;
 	}
 	if (!PKCS12_gen_mac (p12, pass, passlen, mac, &maclen)) {
 		PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_GENERATION_ERROR);
 		return 0;
 	}
 	if (!(M_ASN1_OCTET_STRING_set (p12->mac->dinfo->digest, mac, maclen))) {
 		PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_STRING_SET_ERROR);
 						return 0;
 	}
 	return 1;
 }
 
 /* Set up a mac structure */
 int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
 	     const EVP_MD *md_type)
 {
 	if (!(p12->mac = PKCS12_MAC_DATA_new())) return PKCS12_ERROR;
 	if (iter > 1) {
 		if(!(p12->mac->iter = M_ASN1_INTEGER_new())) {
 			PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
 			return 0;
 		}
 		if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
 			PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
 			return 0;
 		}
 	}
 	if (!saltlen) saltlen = PKCS12_SALT_LEN;
 	p12->mac->salt->length = saltlen;
 	if (!(p12->mac->salt->data = OPENSSL_malloc (saltlen))) {
 		PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
 		return 0;
 	}
 	if (!salt) {
 		if (RAND_pseudo_bytes (p12->mac->salt->data, saltlen) < 0)
 			return 0;
 	}
 	else memcpy (p12->mac->salt->data, salt, saltlen);
 	p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type));
 	if (!(p12->mac->dinfo->algor->parameter = ASN1_TYPE_new())) {
 		PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
 		return 0;
 	}
 	p12->mac->dinfo->algor->parameter->type = V_ASN1_NULL;
 	
 	return 1;
 }
 #endif
Index: releng/10.1/crypto/openssl/crypto/pkcs7/pk7_doit.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284295)
@@ -1,1362 +1,1368 @@
 /* crypto/pkcs7/pk7_doit.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value);
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
 
 static int PKCS7_type_is_other(PKCS7* p7)
 	{
 	int isOther=1;
 	
 	int nid=OBJ_obj2nid(p7->type);
 
 	switch( nid )
 		{
 	case NID_pkcs7_data:
 	case NID_pkcs7_signed:
 	case NID_pkcs7_enveloped:
 	case NID_pkcs7_signedAndEnveloped:
 	case NID_pkcs7_digest:
 	case NID_pkcs7_encrypted:
 		isOther=0;
 		break;
 	default:
 		isOther=1;
 		}
 
 	return isOther;
 
 	}
 
 static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
 	{
 	if ( PKCS7_type_is_data(p7))
 		return p7->d.data;
 	if ( PKCS7_type_is_other(p7) && p7->d.other
 		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
 		return p7->d.other->value.octet_string;
 	return NULL;
 	}
 
 static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
 	{
 	BIO *btmp;
 	const EVP_MD *md;
 	if ((btmp=BIO_new(BIO_f_md())) == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 
 	md=EVP_get_digestbyobj(alg->algorithm);
 	if (md == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 		goto err;
 		}
 
 	BIO_set_md(btmp,md);
 	if (*pbio == NULL)
 		*pbio=btmp;
 	else if (!BIO_push(*pbio,btmp))
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 	btmp=NULL;
 
 	return 1;
 
 	err:
 	if (btmp)
 		BIO_free(btmp);
 	return 0;
 
 	}
 
 static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
 					unsigned char *key, int keylen)
 	{
 	EVP_PKEY_CTX *pctx = NULL;
 	EVP_PKEY *pkey = NULL;
 	unsigned char *ek = NULL;
 	int ret = 0;
 	size_t eklen;
 
 	pkey = X509_get_pubkey(ri->cert);
 
 	if (!pkey)
 		return 0;
 
 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
 	if (!pctx)
 		return 0;
 
 	if (EVP_PKEY_encrypt_init(pctx) <= 0)
 		goto err;
 
 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
 				EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR);
 		goto err;
 		}
 
 	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
 		goto err;
 
 	ek = OPENSSL_malloc(eklen);
 
 	if (ek == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0)
 		goto err;
 
 	ASN1_STRING_set0(ri->enc_key, ek, eklen);
 	ek = NULL;
 
 	ret = 1;
 
 	err:
 	if (pkey)
 		EVP_PKEY_free(pkey);
 	if (pctx)
 		EVP_PKEY_CTX_free(pctx);
 	if (ek)
 		OPENSSL_free(ek);
 	return ret;
 
 	}
 
 
 static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
 			       PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey)
 	{
 	EVP_PKEY_CTX *pctx = NULL;
 	unsigned char *ek = NULL;
 	size_t eklen;
 
 	int ret = -1;
 
 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
 	if (!pctx)
 		return -1;
 
 	if (EVP_PKEY_decrypt_init(pctx) <= 0)
 		goto err;
 
 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
 				EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR);
 		goto err;
 		}
 
 	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
 				ri->enc_key->data, ri->enc_key->length) <= 0)
 		goto err;
 
 	ek = OPENSSL_malloc(eklen);
 
 	if (ek == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
 				ri->enc_key->data, ri->enc_key->length) <= 0)
 		{
 		ret = 0;
 		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB);
 		goto err;
 		}
 
 	ret = 1;
 
 	if (*pek)
 		{
 		OPENSSL_cleanse(*pek, *peklen);
 		OPENSSL_free(*pek);
 		}
 
 	*pek = ek;
 	*peklen = eklen;
 
 	err:
 	if (pctx)
 		EVP_PKEY_CTX_free(pctx);
 	if (!ret && ek)
 		OPENSSL_free(ek);
 
 	return ret;
 	}
 
 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
 	{
 	int i;
 	BIO *out=NULL,*btmp=NULL;
 	X509_ALGOR *xa = NULL;
 	const EVP_CIPHER *evp_cipher=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	X509_ALGOR *xalg=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 	/*
 	 * The content field in the PKCS7 ContentInfo is optional, but that really
 	 * only applies to inner content (precisely, detached signatures).
 	 *
 	 * When reading content, missing outer content is therefore treated as an
 	 * error.
 	 *
 	 * When creating content, PKCS7_content_new() must be called before
 	 * calling this method, so a NULL p7->d is always an error.
 	 */
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		md_sk=p7->d.sign->md_algs;
 		os = PKCS7_get_octet_string(p7->d.sign->contents);
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		xalg=p7->d.enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_digest:
 		xa = p7->d.digest->md;
 		os = PKCS7_get_octet_string(p7->d.digest->contents);
 		break;
 	case NID_pkcs7_data:
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
 	for (i=0; ialgorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
 		if (ivlen > 0)
 			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
 				goto err;
 		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
 			goto err;
 		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
 			goto err;
 
 		if (ivlen > 0) {
 			if (xalg->parameter == NULL) {
 				xalg->parameter = ASN1_TYPE_new();
 				if (xalg->parameter == NULL)
 					goto err;
 			}
 			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
 				goto err;
 		}
 
 		/* Lets do the pub key stuff :-) */
 		for (i=0; ilength > 0)
 			bio = BIO_new_mem_buf(os->data, os->length);
 		if(bio == NULL)
 			{
 			bio=BIO_new(BIO_s_mem());
 			if (bio == NULL)
 				goto err;
 			BIO_set_mem_eof_return(bio,0);
 			}
 		}
 	if (out)
 		BIO_push(out,bio);
 	else
 		out = bio;
 	bio=NULL;
 	if (0)
 		{
 err:
 		if (out != NULL)
 			BIO_free_all(out);
 		if (btmp != NULL)
 			BIO_free_all(btmp);
 		out=NULL;
 		}
 	return(out);
 	}
 
 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
 	{
 	int ret;
 	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
 				pcert->cert_info->issuer);
 	if (ret)
 		return ret;
 	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
 					ri->issuer_and_serial->serial);
 	}
 
 /* int */
 BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 	{
 	int i,j;
 	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
 	X509_ALGOR *xa;
 	ASN1_OCTET_STRING *data_body=NULL;
 	const EVP_MD *evp_md;
 	const EVP_CIPHER *evp_cipher=NULL;
 	EVP_CIPHER_CTX *evp_ctx=NULL;
 	X509_ALGOR *enc_alg=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
        unsigned char *ek = NULL, *tkey = NULL;
        int eklen = 0, tkeylen = 0;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
 		if (!PKCS7_is_detached(p7) && data_body == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_INVALID_SIGNED_DATA_TYPE);
 			goto err;
 			}
 		md_sk=p7->d.sign->md_algs;
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
 		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		enc_alg=p7->d.enveloped->enc_data->algorithm;
 		data_body=p7->d.enveloped->enc_data->enc_data;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
+    /* Detached content must be supplied via in_bio instead. */
+    if (data_body == NULL && in_bio == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+        goto err;
+    }
+
 	/* We will be checking the signature */
 	if (md_sk != NULL)
 		{
 		for (i=0; ialgorithm);
 			evp_md=EVP_get_digestbynid(j);
 			if (evp_md == NULL)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 				goto err;
 				}
 
 			BIO_set_md(btmp,evp_md);
 			if (out == NULL)
 				out=btmp;
 			else
 				BIO_push(out,btmp);
 			btmp=NULL;
 			}
 		}
 
 	if (evp_cipher != NULL)
 		{
 #if 0
 		unsigned char key[EVP_MAX_KEY_LENGTH];
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char *p;
 		int keylen,ivlen;
 		int max;
 		X509_OBJECT ret;
 #endif
 
 		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
 			goto err;
 			}
 
 		/* It was encrypted, we need to decrypt the secret key
 		 * with the private key */
 
 		/* Find the recipientInfo which matches the passed certificate
 		 * (if any)
 		 */
 
 		if (pcert)
 			{
 			for (i=0; iparameter) < 0)
 			goto err;
 		/* Generate random key as MMA defence */
 		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
 		tkey = OPENSSL_malloc(tkeylen);
 		if (!tkey)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
 			goto err;
 		if (ek == NULL)
 			{
 			ek = tkey;
 			eklen = tkeylen;
 			tkey = NULL;
 			}
 
 		if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
 			/* Some S/MIME clients don't use the same key
 			 * and effective key length. The key length is
 			 * determined by the size of the decrypted RSA key.
 			 */
 			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen))
 				{
 				/* Use random key as MMA defence */
 				OPENSSL_cleanse(ek, eklen);
 				OPENSSL_free(ek);
 				ek = tkey;
 				eklen = tkeylen;
 				tkey = NULL;
 				}
 		} 
 		/* Clear errors so we don't leak information useful in MMA */
 		ERR_clear_error();
 		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0)
 			goto err;
 
 		if (ek)
 			{
 			OPENSSL_cleanse(ek,eklen);
 			OPENSSL_free(ek);
                        ek = NULL;
 			}
 		if (tkey)
 			{
 			OPENSSL_cleanse(tkey,tkeylen);
 			OPENSSL_free(tkey);
                        tkey = NULL;
 			}
 
 		if (out == NULL)
 			out=etmp;
 		else
 			BIO_push(out,etmp);
 		etmp=NULL;
 		}
 
 #if 1
-	if (PKCS7_is_detached(p7) || (in_bio != NULL))
+	if (in_bio != NULL)
 		{
 		bio=in_bio;
 		}
 	else 
 		{
 #if 0
 		bio=BIO_new(BIO_s_mem());
 		/* We need to set this so that when we have read all
 		 * the data, the encrypt BIO, if present, will read
 		 * EOF and encode the last few bytes */
 		BIO_set_mem_eof_return(bio,0);
 
 		if (data_body->length > 0)
 			BIO_write(bio,(char *)data_body->data,data_body->length);
 #else
 		if (data_body->length > 0)
 		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
 		else {
 			bio=BIO_new(BIO_s_mem());
 			BIO_set_mem_eof_return(bio,0);
 		}
 		if (bio == NULL)
 			goto err;
 #endif
 		}
 	BIO_push(out,bio);
 	bio=NULL;
 #endif
 	if (0)
 		{
 err:
                if (ek)
                        {
                        OPENSSL_cleanse(ek,eklen);
                        OPENSSL_free(ek);
                        }
                if (tkey)
                        {
                        OPENSSL_cleanse(tkey,tkeylen);
                        OPENSSL_free(tkey);
                        }
 		if (out != NULL) BIO_free_all(out);
 		if (btmp != NULL) BIO_free_all(btmp);
 		if (etmp != NULL) BIO_free_all(etmp);
 		if (bio != NULL) BIO_free_all(bio);
 		out=NULL;
 		}
 	return(out);
 	}
 
 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
 	{
 	for (;;)
 		{
 		bio=BIO_find_type(bio,BIO_TYPE_MD);
 		if (bio == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			return NULL;	
 			}
 		BIO_get_md_ctx(bio,pmd);
 		if (*pmd == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}	
 		if (EVP_MD_CTX_type(*pmd) == nid)
 			return bio;
 		bio=BIO_next(bio);
 		}
 	return NULL;
 	}
 
 static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
 	{
 	unsigned char md_data[EVP_MAX_MD_SIZE];
 	unsigned int md_len;
 
 	/* Add signing time if not already present */
 	if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime))
 		{
 		if (!PKCS7_add0_attrib_signing_time(si, NULL))
 			{
 			PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB,
 					ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		}
 
 	/* Add digest */
 	if (!EVP_DigestFinal_ex(mctx, md_data,&md_len))
 		{
 		PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB);
 		return 0;
 		}
 	if (!PKCS7_add1_attrib_digest(si, md_data, md_len))
 		{
 		PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	/* Now sign the attributes */
 	if (!PKCS7_SIGNER_INFO_sign(si))
 			return 0;
 
 	return 1;
 	}
 	
 				
 int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 	{
 	int ret=0;
 	int i,j;
 	BIO *btmp;
 	PKCS7_SIGNER_INFO *si;
 	EVP_MD_CTX *mdc,ctx_tmp;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	EVP_MD_CTX_init(&ctx_tmp);
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_data:
 		os = p7->d.data;
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		/* XXXXXXXXXXXXXXXX */
 		si_sk=p7->d.signed_and_enveloped->signer_info;
 		os = p7->d.signed_and_enveloped->enc_data->enc_data;
 		if (!os)
 			{
 			os=M_ASN1_OCTET_STRING_new();
 			if (!os)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 			p7->d.signed_and_enveloped->enc_data->enc_data=os;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		/* XXXXXXXXXXXXXXXX */
 		os = p7->d.enveloped->enc_data->enc_data;
 		if (!os)
 			{
 			os=M_ASN1_OCTET_STRING_new();
 			if (!os)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 			p7->d.enveloped->enc_data->enc_data=os;
 			}
 		break;
 	case NID_pkcs7_signed:
 		si_sk=p7->d.sign->signer_info;
 		os=PKCS7_get_octet_string(p7->d.sign->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.sign->contents->d.data = NULL;
 		}
 		break;
 
 	case NID_pkcs7_digest:
 		os=PKCS7_get_octet_string(p7->d.digest->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
 			{
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.digest->contents->d.data = NULL;
 			}
 		break;
 
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
 	if (si_sk != NULL)
 		{
 		for (i=0; ipkey == NULL)
 				continue;
 
 			j = OBJ_obj2nid(si->digest_alg->algorithm);
 
 			btmp=bio;
 
 			btmp = PKCS7_find_digest(&mdc, btmp, j);
 
 			if (btmp == NULL)
 				goto err;
 
 			/* We now have the EVP_MD_CTX, lets do the
 			 * signing. */
 			if (!EVP_MD_CTX_copy_ex(&ctx_tmp,mdc))
 				goto err;
 
 			sk=si->auth_attr;
 
 			/* If there are attributes, we add the digest
 			 * attribute and only sign the attributes */
 			if (sk_X509_ATTRIBUTE_num(sk) > 0)
 				{
 				if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
 					goto err;
 				}
 			else
 				{
 				unsigned char *abuf = NULL;
 				unsigned int abuflen;
 				abuflen = EVP_PKEY_size(si->pkey);
 				abuf = OPENSSL_malloc(abuflen);
 				if (!abuf)
 					goto err;
 
 				if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen,
 							si->pkey))
 					{
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 							ERR_R_EVP_LIB);
 					goto err;
 					}
 				ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
 				}
 			}
 		}
 	else if (i == NID_pkcs7_digest) {
 		unsigned char md_data[EVP_MAX_MD_SIZE];
 		unsigned int md_len;
 		if (!PKCS7_find_digest(&mdc, bio,
 				OBJ_obj2nid(p7->d.digest->md->algorithm)))
 			goto err;
 		if (!EVP_DigestFinal_ex(mdc,md_data,&md_len))
 			goto err;
 		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
 		}
 
 		if (!PKCS7_is_detached(p7)) {
 			/*
 			 * NOTE(emilia): I think we only reach os == NULL here because detached
 			 * digested data support is broken.
 			 */
 			if (os == NULL)
 				goto err;
 			if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
 				char *cont;
 				long contlen;
 				btmp = BIO_find_type(bio, BIO_TYPE_MEM);
 				if (btmp == NULL) {
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
 				goto err;
 			}
 			contlen = BIO_get_mem_data(btmp, &cont);
 			/*
 			 * Mark the BIO read only then we can use its copy of the data
 			 * instead of making an extra copy.
 			 */
 			BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
 			BIO_set_mem_eof_return(btmp, 0);
 			ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
 		}
 	}
 	ret=1;
 err:
 	EVP_MD_CTX_cleanup(&ctx_tmp);
 	return(ret);
 	}
 
 int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
 	{
 	EVP_MD_CTX mctx;
 	EVP_PKEY_CTX *pctx;
 	unsigned char *abuf = NULL;
 	int alen;
 	size_t siglen;
 	const EVP_MD *md = NULL;
 
 	md = EVP_get_digestbyobj(si->digest_alg->algorithm);
 	if (md == NULL)
 		return 0;
 
 	EVP_MD_CTX_init(&mctx);
 	if (EVP_DigestSignInit(&mctx, &pctx, md,NULL, si->pkey) <= 0)
 		goto err;
 
 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
 				EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
 		goto err;
 		}
 
 	alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf,
 				ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
 	if(!abuf)
 		goto err;
 	if (EVP_DigestSignUpdate(&mctx,abuf,alen) <= 0)
 		goto err;
 	OPENSSL_free(abuf);
 	abuf = NULL;
 	if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
 		goto err;
 	abuf = OPENSSL_malloc(siglen);
 	if(!abuf)
 		goto err;
 	if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
 		goto err;
 
 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
 				EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
 		goto err;
 		}
 
 	EVP_MD_CTX_cleanup(&mctx);
 
 	ASN1_STRING_set0(si->enc_digest, abuf, siglen);
 
 	return 1;
 
 	err:
 	if (abuf)
 		OPENSSL_free(abuf);
 	EVP_MD_CTX_cleanup(&mctx);
 	return 0;
 
 	}
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
 	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 	{
 	PKCS7_ISSUER_AND_SERIAL *ias;
 	int ret=0,i;
 	STACK_OF(X509) *cert;
 	X509 *x509;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	if (PKCS7_type_is_signed(p7))
 		{
 		cert=p7->d.sign->cert;
 		}
 	else if (PKCS7_type_is_signedAndEnveloped(p7))
 		{
 		cert=p7->d.signed_and_enveloped->cert;
 		}
 	else
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 		}
 	/* XXXXXXXXXXXXXXXXXXXXXXX */
 	ias=si->issuer_and_serial;
 
 	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
 
 	/* were we able to find the cert in passed to us */
 	if (x509 == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
 		goto err;
 		}
 
 	/* Lets verify */
 	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		goto err;
 		}
 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
 	i=X509_verify_cert(ctx);
 	if (i <= 0) 
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		X509_STORE_CTX_cleanup(ctx);
 		goto err;
 		}
 	X509_STORE_CTX_cleanup(ctx);
 
 	return PKCS7_signatureVerify(bio, p7, si, x509);
 	err:
 	return ret;
 	}
 
 int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
 								X509 *x509)
 	{
 	ASN1_OCTET_STRING *os;
 	EVP_MD_CTX mdc_tmp,*mdc;
 	int ret=0,i;
 	int md_type;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	BIO *btmp;
 	EVP_PKEY *pkey;
 
 	EVP_MD_CTX_init(&mdc_tmp);
 
 	if (!PKCS7_type_is_signed(p7) && 
 				!PKCS7_type_is_signedAndEnveloped(p7)) {
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 	}
 
 	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
 
 	btmp=bio;
 	for (;;)
 		{
 		if ((btmp == NULL) ||
 			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		BIO_get_md_ctx(btmp,&mdc);
 		if (mdc == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 							ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		if (EVP_MD_CTX_type(mdc) == md_type)
 			break;
 		/* Workaround for some broken clients that put the signature
 		 * OID instead of the digest OID in digest_alg->algorithm
 		 */
 		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
 			break;
 		btmp=BIO_next(btmp);
 		}
 
 	/* mdc is the digest ctx that we want, unless there are attributes,
 	 * in which case the digest is the signed attributes */
 	if (!EVP_MD_CTX_copy_ex(&mdc_tmp,mdc))
 		goto err;
 
 	sk=si->auth_attr;
 	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
 		{
 		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
                 unsigned int md_len;
 		int alen;
 		ASN1_OCTET_STRING *message_digest;
 
 		if (!EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len))
 			goto err;
 		message_digest=PKCS7_digest_from_attributes(sk);
 		if (!message_digest)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		if ((message_digest->length != (int)md_len) ||
 			(memcmp(message_digest->data,md_dat,md_len)))
 			{
 #if 0
 {
 int ii;
 for (ii=0; iilength; ii++)
 	printf("%02X",message_digest->data[ii]); printf(" sent\n");
 for (ii=0; iienc_digest;
 	pkey = X509_get_pubkey(x509);
 	if (!pkey)
 		{
 		ret = -1;
 		goto err;
 		}
 
 	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
 	EVP_PKEY_free(pkey);
 	if (i <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_SIGNATURE_FAILURE);
 		ret= -1;
 		goto err;
 		}
 	else
 		ret=1;
 err:
 	EVP_MD_CTX_cleanup(&mdc_tmp);
 	return(ret);
 	}
 
 PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
 	{
 	STACK_OF(PKCS7_RECIP_INFO) *rsk;
 	PKCS7_RECIP_INFO *ri;
 	int i;
 
 	i=OBJ_obj2nid(p7->type);
 	if (i != NID_pkcs7_signedAndEnveloped)
 		return NULL;
 	if (p7->d.signed_and_enveloped == NULL)
 		return NULL;
 	rsk=p7->d.signed_and_enveloped->recipientinfo;
 	if (rsk == NULL)
 		return NULL;
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
 	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
 	return(ri->issuer_and_serial);
 	}
 
 ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->auth_attr,nid));
 	}
 
 ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->unauth_attr,nid));
 	}
 
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
 	{
 	int i;
 	X509_ATTRIBUTE *xa;
 	ASN1_OBJECT *o;
 
 	o=OBJ_nid2obj(nid);
 	if (!o || !sk) return(NULL);
 	for (i=0; iobject,o) == 0)
 			{
 			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
 				return(sk_ASN1_TYPE_value(xa->value.set,0));
 			else
 				return(NULL);
 			}
 		}
 	return(NULL);
 	}
 
 ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
 {
 	ASN1_TYPE *astype;
 	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
 	return astype->value.octet_string;
 }
 
 int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
 				STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->auth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
 	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->auth_attr == NULL)
 		return 0;
 	for (i=0; iauth_attr,i,
 			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->unauth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
 					   X509_ATTRIBUTE_free);
 	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->unauth_attr == NULL)
 		return 0;
 	for (i=0; iunauth_attr,i,
                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
 	}
 
 int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
 	}
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value)
 	{
 	X509_ATTRIBUTE *attr=NULL;
 
 	if (*sk == NULL)
 		{
 		*sk = sk_X509_ATTRIBUTE_new_null();
 		if (*sk == NULL)
 			return 0;	
 new_attrib:
 		if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value)))
 			return 0;
 		if (!sk_X509_ATTRIBUTE_push(*sk,attr))
 			{
 			X509_ATTRIBUTE_free(attr);
 			return 0;
 			}
 		}
 	else
 		{
 		int i;
 
 		for (i=0; iobject) == nid)
 				{
 				X509_ATTRIBUTE_free(attr);
 				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
 				if (attr == NULL)
 					return 0;
 				if (!sk_X509_ATTRIBUTE_set(*sk,i,attr))
 					{
 					X509_ATTRIBUTE_free(attr);
 					return 0;
 					}
 				goto end;
 				}
 			}
 		goto new_attrib;
 		}
 end:
 	return(1);
 	}
 
Index: releng/10.1/crypto/openssl/crypto/x509/x509_vfy.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284295)
@@ -1,2224 +1,2262 @@
 /* crypto/x509/x509_vfy.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
 /* CRL score values */
 
 /* No unhandled critical extensions */
 
 #define CRL_SCORE_NOCRITICAL	0x100
 
 /* certificate is within CRL scope */
 
 #define CRL_SCORE_SCOPE		0x080
 
 /* CRL times valid */
 
 #define CRL_SCORE_TIME		0x040
 
 /* Issuer name matches certificate */
 
 #define CRL_SCORE_ISSUER_NAME	0x020
 
 /* If this score or above CRL is probably valid */
 
 #define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE)
 
 /* CRL issuer is certificate issuer */
 
 #define CRL_SCORE_ISSUER_CERT	0x018
 
 /* CRL issuer is on certificate path */
 
 #define CRL_SCORE_SAME_PATH	0x008
 
 /* CRL issuer matches CRL AKID */
 
 #define CRL_SCORE_AKID		0x004
 
 /* Have a delta CRL with valid times */
 
 #define CRL_SCORE_TIME_DELTA	0x002
 
 static int null_callback(int ok,X509_STORE_CTX *e);
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
 static int check_chain_extensions(X509_STORE_CTX *ctx);
 static int check_name_constraints(X509_STORE_CTX *ctx);
 static int check_trust(X509_STORE_CTX *ctx);
 static int check_revocation(X509_STORE_CTX *ctx);
 static int check_cert(X509_STORE_CTX *ctx);
 static int check_policy(X509_STORE_CTX *ctx);
 
 static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
 			unsigned int *preasons,
 			X509_CRL *crl, X509 *x);
 static int get_crl_delta(X509_STORE_CTX *ctx,
 				X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
 static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score,
 			X509_CRL *base, STACK_OF(X509_CRL) *crls);
 static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
 				X509 **pissuer, int *pcrl_score);
 static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
 				unsigned int *preasons);
 static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
 static int check_crl_chain(X509_STORE_CTX *ctx,
 			STACK_OF(X509) *cert_path,
 			STACK_OF(X509) *crl_path);
 
 static int internal_verify(X509_STORE_CTX *ctx);
 const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT;
 
 
 static int null_callback(int ok, X509_STORE_CTX *e)
 	{
 	return ok;
 	}
 
 #if 0
 static int x509_subject_cmp(X509 **a, X509 **b)
 	{
 	return X509_subject_name_cmp(*a,*b);
 	}
 #endif
 
 int X509_verify_cert(X509_STORE_CTX *ctx)
 	{
 	X509 *x,*xtmp,*chain_ss=NULL;
 	int bad_chain = 0;
 	X509_VERIFY_PARAM *param = ctx->param;
 	int depth,i,ok=0;
 	int num;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	STACK_OF(X509) *sktmp=NULL;
 	if (ctx->cert == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
 		return -1;
 		}
 
 	cb=ctx->verify_cb;
 
 	/* first we make sure the chain we are going to build is
 	 * present and that the first entry is in place */
 	if (ctx->chain == NULL)
 		{
 		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
 			(!sk_X509_push(ctx->chain,ctx->cert)))
 			{
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			goto end;
 			}
 		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
 		ctx->last_untrusted=1;
 		}
 
 	/* We use a temporary STACK so we can chop and hack at it */
 	if (ctx->untrusted != NULL
 	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 		goto end;
 		}
 
 	num=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,num-1);
 	depth=param->depth;
 
 
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break; /* FIXME: If this happens, we should take
 		                         * note of it and, if appropriate, use the
 		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
 		                         * code later.
 		                         */
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx, x,x)) break;
 
 		/* If we were passed a cert chain, use it first */
 		if (ctx->untrusted != NULL)
 			{
 			xtmp=find_issuer(ctx, sktmp,x);
 			if (xtmp != NULL)
 				{
 				if (!sk_X509_push(ctx->chain,xtmp))
 					{
 					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 					goto end;
 					}
 				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
 				(void)sk_X509_delete_ptr(sktmp,xtmp);
 				ctx->last_untrusted++;
 				x=xtmp;
 				num++;
 				/* reparse the full chain for
 				 * the next one */
 				continue;
 				}
 			}
 		break;
 		}
 
 	/* at this point, chain should contain a list of untrusted
 	 * certificates.  We now need to add at least one trusted one,
 	 * if possible, otherwise we complain. */
 
 	/* Examine last certificate in chain and see if it
  	 * is self signed.
  	 */
 
 	i=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,i-1);
 	if (ctx->check_issued(ctx, x, x))
 		{
 		/* we have a self signed certificate */
 		if (sk_X509_num(ctx->chain) == 1)
 			{
 			/* We have a single self signed certificate: see if
 			 * we can find it in the store. We must have an exact
 			 * match to avoid possible impersonation.
 			 */
 			ok = ctx->get_issuer(&xtmp, ctx, x);
 			if ((ok <= 0) || X509_cmp(x, xtmp)) 
 				{
 				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
 				ctx->current_cert=x;
 				ctx->error_depth=i-1;
 				if (ok == 1) X509_free(xtmp);
 				bad_chain = 1;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			else 
 				{
 				/* We have a match: replace certificate with store version
 				 * so we get any trust settings.
 				 */
 				X509_free(x);
 				x = xtmp;
 				(void)sk_X509_set(ctx->chain, i - 1, x);
 				ctx->last_untrusted=0;
 				}
 			}
 		else
 			{
 			/* extract and save self signed certificate for later use */
 			chain_ss=sk_X509_pop(ctx->chain);
 			ctx->last_untrusted--;
 			num--;
 			x=sk_X509_value(ctx->chain,num-1);
 			}
 		}
 
 	/* We now lookup certs from the certificate store */
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break;
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx,x,x)) break;
 
 		ok = ctx->get_issuer(&xtmp, ctx, x);
 
 		if (ok < 0) return ok;
 		if (ok == 0) break;
 
 		x = xtmp;
 		if (!sk_X509_push(ctx->chain,x))
 			{
 			X509_free(xtmp);
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		num++;
 		}
 
 	/* we now have our chain, lets check it... */
 
 	/* Is last certificate looked up self signed? */
 	if (!ctx->check_issued(ctx,x,x))
 		{
 		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
 			{
 			if (ctx->last_untrusted >= num)
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
 			else
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
 			ctx->current_cert=x;
 			}
 		else
 			{
 
 			sk_X509_push(ctx->chain,chain_ss);
 			num++;
 			ctx->last_untrusted=num;
 			ctx->current_cert=chain_ss;
 			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
 			chain_ss=NULL;
 			}
 
 		ctx->error_depth=num-1;
 		bad_chain = 1;
 		ok=cb(0,ctx);
 		if (!ok) goto end;
 		}
 
 	/* We have the chain complete: now we need to check its purpose */
 	ok = check_chain_extensions(ctx);
 
 	if (!ok) goto end;
 
 	/* Check name constraints */
 
 	ok = check_name_constraints(ctx);
 	
 	if (!ok) goto end;
 
 	/* The chain extensions are OK: check trust */
 
 	if (param->trust > 0) ok = check_trust(ctx);
 
 	if (!ok) goto end;
 
 	/* We may as well copy down any DSA parameters that are required */
 	X509_get_pubkey_parameters(NULL,ctx->chain);
 
 	/* Check revocation status: we do this after copying parameters
 	 * because they may be needed for CRL signature verification.
 	 */
 
 	ok = ctx->check_revocation(ctx);
 	if(!ok) goto end;
 
 	/* At this point, we have a chain and need to verify it */
 	if (ctx->verify != NULL)
 		ok=ctx->verify(ctx);
 	else
 		ok=internal_verify(ctx);
 	if(!ok) goto end;
 
 #ifndef OPENSSL_NO_RFC3779
 	/* RFC 3779 path validation, now that CRL check has been done */
 	ok = v3_asid_validate_path(ctx);
 	if (!ok) goto end;
 	ok = v3_addr_validate_path(ctx);
 	if (!ok) goto end;
 #endif
 
 	/* If we get this far evaluate policies */
 	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
 		ok = ctx->check_policy(ctx);
 	if(!ok) goto end;
 	if (0)
 		{
 end:
 		X509_get_pubkey_parameters(NULL,ctx->chain);
 		}
 	if (sktmp != NULL) sk_X509_free(sktmp);
 	if (chain_ss != NULL) X509_free(chain_ss);
 	return ok;
 	}
 
 
 /* Given a STACK_OF(X509) find the issuer of cert (if any)
  */
 
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
 {
 	int i;
 	X509 *issuer;
 	for (i = 0; i < sk_X509_num(sk); i++)
 		{
 		issuer = sk_X509_value(sk, i);
 		if (ctx->check_issued(ctx, x, issuer))
 			return issuer;
 		}
 	return NULL;
 }
 
 /* Given a possible certificate and issuer check them */
 
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
 {
 	int ret;
 	ret = X509_check_issued(issuer, x);
 	if (ret == X509_V_OK)
 		return 1;
 	/* If we haven't asked for issuer errors don't set ctx */
 	if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
 		return 0;
 
 	ctx->error = ret;
 	ctx->current_cert = x;
 	ctx->current_issuer = issuer;
 	return ctx->verify_cb(0, ctx);
 	return 0;
 }
 
 /* Alternative lookup method: look from a STACK stored in other_ctx */
 
 static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 {
 	*issuer = find_issuer(ctx, ctx->other_ctx, x);
 	if (*issuer)
 		{
 		CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
 		return 1;
 		}
 	else
 		return 0;
 }
 	
 
 /* Check a certificate chains extensions for consistency
  * with the supplied purpose
  */
 
 static int check_chain_extensions(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok=0, must_be_ca, plen = 0;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	int proxy_path_length = 0;
 	int purpose;
 	int allow_proxy_certs;
 	cb=ctx->verify_cb;
 
 	/* must_be_ca can have 1 of 3 values:
 	   -1: we accept both CA and non-CA certificates, to allow direct
 	       use of self-signed certificates (which are marked as CA).
 	   0:  we only accept non-CA certificates.  This is currently not
 	       used, but the possibility is present for future extensions.
 	   1:  we only accept CA certificates.  This is currently used for
 	       all certificates in the chain except the leaf certificate.
 	*/
 	must_be_ca = -1;
 
 	/* CRL path validation */
 	if (ctx->parent)
 		{
 		allow_proxy_certs = 0;
 		purpose = X509_PURPOSE_CRL_SIGN;
 		}
 	else
 		{
 		allow_proxy_certs =
 			!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
 		/* A hack to keep people who don't want to modify their
 		   software happy */
 		if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
 			allow_proxy_certs = 1;
 		purpose = ctx->param->purpose;
 		}
 
 	/* Check all untrusted certificates */
 	for (i = 0; i < ctx->last_untrusted; i++)
 		{
 		int ret;
 		x = sk_X509_value(ctx->chain, i);
 		if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 			&& (x->ex_flags & EXFLAG_CRITICAL))
 			{
 			ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
 			{
 			ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		ret = X509_check_ca(x);
 		switch(must_be_ca)
 			{
 		case -1:
 			if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 				&& (ret != 1) && (ret != 0))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 		case 0:
 			if (ret != 0)
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_NON_CA;
 				}
 			else
 				ret = 1;
 			break;
 		default:
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 			}
 		if (ret == 0)
 			{
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (ctx->param->purpose > 0)
 			{
 			ret = X509_check_purpose(x, purpose, must_be_ca > 0);
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ctx->error = X509_V_ERR_INVALID_PURPOSE;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			}
 		/* Check pathlen if not self issued */
 		if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
 			   && (x->ex_pathlen != -1)
 			   && (plen > (x->ex_pathlen + proxy_path_length + 1)))
 			{
 			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		/* Increment path length if not self issued */
 		if (!(x->ex_flags & EXFLAG_SI))
 			plen++;
 		/* If this certificate is a proxy certificate, the next
 		   certificate must be another proxy certificate or a EE
 		   certificate.  If not, the next certificate must be a
 		   CA certificate.  */
 		if (x->ex_flags & EXFLAG_PROXY)
 			{
 			if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
 				{
 				ctx->error =
 					X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			proxy_path_length++;
 			must_be_ca = 0;
 			}
 		else
 			must_be_ca = 1;
 		}
 	ok = 1;
  end:
 	return ok;
 #endif
 }
 
 static int check_name_constraints(X509_STORE_CTX *ctx)
 	{
 	X509 *x;
 	int i, j, rv;
 	/* Check name constraints for all certificates */
 	for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--)
 		{
 		x = sk_X509_value(ctx->chain, i);
 		/* Ignore self issued certs unless last in chain */
 		if (i && (x->ex_flags & EXFLAG_SI))
 			continue;
 		/* Check against constraints for all certificates higher in
 		 * chain including trust anchor. Trust anchor not strictly
 		 * speaking needed but if it includes constraints it is to be
 		 * assumed it expects them to be obeyed.
 		 */
 		for (j = sk_X509_num(ctx->chain) - 1; j > i; j--)
 			{
 			NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
 			if (nc)
 				{
 				rv = NAME_CONSTRAINTS_check(x, nc);
 				if (rv != X509_V_OK)
 					{
 					ctx->error = rv;
 					ctx->error_depth = i;
 					ctx->current_cert = x;
 					if (!ctx->verify_cb(0,ctx))
 						return 0;
 					}
 				}
 			}
 		}
 	return 1;
 	}
 
 static int check_trust(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	cb=ctx->verify_cb;
 /* For now just check the last certificate in the chain */
 	i = sk_X509_num(ctx->chain) - 1;
 	x = sk_X509_value(ctx->chain, i);
 	ok = X509_check_trust(x, ctx->param->trust, 0);
 	if (ok == X509_TRUST_TRUSTED)
 		return 1;
 	ctx->error_depth = i;
 	ctx->current_cert = x;
 	if (ok == X509_TRUST_REJECTED)
 		ctx->error = X509_V_ERR_CERT_REJECTED;
 	else
 		ctx->error = X509_V_ERR_CERT_UNTRUSTED;
 	ok = cb(0, ctx);
 	return ok;
 #endif
 }
 
 static int check_revocation(X509_STORE_CTX *ctx)
 	{
 	int i, last, ok;
 	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
 		return 1;
 	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
 		last = sk_X509_num(ctx->chain) - 1;
 	else
 		{
 		/* If checking CRL paths this isn't the EE certificate */
 		if (ctx->parent)
 			return 1;
 		last = 0;
 		}
 	for(i = 0; i <= last; i++)
 		{
 		ctx->error_depth = i;
 		ok = check_cert(ctx);
 		if (!ok) return ok;
 		}
 	return 1;
 	}
 
 static int check_cert(X509_STORE_CTX *ctx)
 	{
 	X509_CRL *crl = NULL, *dcrl = NULL;
 	X509 *x;
 	int ok, cnum;
 	unsigned int last_reasons;
 	cnum = ctx->error_depth;
 	x = sk_X509_value(ctx->chain, cnum);
 	ctx->current_cert = x;
 	ctx->current_issuer = NULL;
 	ctx->current_crl_score = 0;
 	ctx->current_reasons = 0;
 	while (ctx->current_reasons != CRLDP_ALL_REASONS)
 		{
 		last_reasons = ctx->current_reasons;
 		/* Try to retrieve relevant CRL */
 		if (ctx->get_crl)
 			ok = ctx->get_crl(ctx, &crl, x);
 		else
 			ok = get_crl_delta(ctx, &crl, &dcrl, x);
 		/* If error looking up CRL, nothing we can do except
 		 * notify callback
 		 */
 		if(!ok)
 			{
 			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
 			ok = ctx->verify_cb(0, ctx);
 			goto err;
 			}
 		ctx->current_crl = crl;
 		ok = ctx->check_crl(ctx, crl);
 		if (!ok)
 			goto err;
 
 		if (dcrl)
 			{
 			ok = ctx->check_crl(ctx, dcrl);
 			if (!ok)
 				goto err;
 			ok = ctx->cert_crl(ctx, dcrl, x);
 			if (!ok)
 				goto err;
 			}
 		else
 			ok = 1;
 
 		/* Don't look in full CRL if delta reason is removefromCRL */
 		if (ok != 2)
 			{
 			ok = ctx->cert_crl(ctx, crl, x);
 			if (!ok)
 				goto err;
 			}
 
 		X509_CRL_free(crl);
 		X509_CRL_free(dcrl);
 		crl = NULL;
 		dcrl = NULL;
 		/* If reasons not updated we wont get anywhere by
 		 * another iteration, so exit loop.
 		 */
 		if (last_reasons == ctx->current_reasons)
 			{
 			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
 			ok = ctx->verify_cb(0, ctx);
 			goto err;
 			}
 		}
 	err:
 	X509_CRL_free(crl);
 	X509_CRL_free(dcrl);
 
 	ctx->current_crl = NULL;
 	return ok;
 
 	}
 
 /* Check CRL times against values in X509_STORE_CTX */
 
 static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
 	{
 	time_t *ptime;
 	int i;
 	if (notify)
 		ctx->current_crl = crl;
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
 	if (i == 0)
 		{
 		if (!notify)
 			return 0;
 		ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		if (!notify)
 			return 0;
 		ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if(X509_CRL_get_nextUpdate(crl))
 		{
 		i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
 
 		if (i == 0)
 			{
 			if (!notify)
 				return 0;
 			ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
 			if (!ctx->verify_cb(0, ctx))
 				return 0;
 			}
 		/* Ignore expiry of base CRL is delta is valid */
 		if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA))
 			{
 			if (!notify)
 				return 0;
 			ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
 			if (!ctx->verify_cb(0, ctx))
 				return 0;
 			}
 		}
 
 	if (notify)
 		ctx->current_crl = NULL;
 
 	return 1;
 	}
 
 static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
 			X509 **pissuer, int *pscore, unsigned int *preasons,
 			STACK_OF(X509_CRL) *crls)
 	{
 	int i, crl_score, best_score = *pscore;
 	unsigned int reasons, best_reasons = 0;
 	X509 *x = ctx->current_cert;
 	X509_CRL *crl, *best_crl = NULL;
 	X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
 
 	for (i = 0; i < sk_X509_CRL_num(crls); i++)
 		{
 		crl = sk_X509_CRL_value(crls, i);
 		reasons = *preasons;
 		crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
 
 		if (crl_score > best_score)
 			{
 			best_crl = crl;
 			best_crl_issuer = crl_issuer;
 			best_score = crl_score;
 			best_reasons = reasons;
 			}
 		}
 
 	if (best_crl)
 		{
 		if (*pcrl)
 			X509_CRL_free(*pcrl);
 		*pcrl = best_crl;
 		*pissuer = best_crl_issuer;
 		*pscore = best_score;
 		*preasons = best_reasons;
 		CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL);
 		if (*pdcrl)
 			{
 			X509_CRL_free(*pdcrl);
 			*pdcrl = NULL;
 			}
 		get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
 		}
 
 	if (best_score >= CRL_SCORE_VALID)
 		return 1;
 
 	return 0;
 	}
 
 /* Compare two CRL extensions for delta checking purposes. They should be
  * both present or both absent. If both present all fields must be identical.
  */
 
 static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
 	{
 	ASN1_OCTET_STRING *exta, *extb;
 	int i;
 	i = X509_CRL_get_ext_by_NID(a, nid, -1);
 	if (i >= 0)
 		{
 		/* Can't have multiple occurrences */
 		if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
 			return 0;
 		exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
 		}
 	else
 		exta = NULL;
 
 	i = X509_CRL_get_ext_by_NID(b, nid, -1);
 
 	if (i >= 0)
 		{
 
 		if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
 			return 0;
 		extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
 		}
 	else
 		extb = NULL;
 
 	if (!exta && !extb)
 		return 1;
 
 	if (!exta || !extb)
 		return 0;
 
 
 	if (ASN1_OCTET_STRING_cmp(exta, extb))
 		return 0;
 
 	return 1;
 	}
 
 /* See if a base and delta are compatible */
 
 static int check_delta_base(X509_CRL *delta, X509_CRL *base)
 	{
 	/* Delta CRL must be a delta */
 	if (!delta->base_crl_number)
 			return 0;
 	/* Base must have a CRL number */
 	if (!base->crl_number)
 			return 0;
 	/* Issuer names must match */
 	if (X509_NAME_cmp(X509_CRL_get_issuer(base),
 				X509_CRL_get_issuer(delta)))
 		return 0;
 	/* AKID and IDP must match */
 	if (!crl_extension_match(delta, base, NID_authority_key_identifier))
 			return 0;
 	if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
 			return 0;
 	/* Delta CRL base number must not exceed Full CRL number. */
 	if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
 			return 0;
 	/* Delta CRL number must exceed full CRL number */
 	if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
 			return 1;
 	return 0;
 	}
 
 /* For a given base CRL find a delta... maybe extend to delta scoring
  * or retrieve a chain of deltas...
  */
 
 static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
 			X509_CRL *base, STACK_OF(X509_CRL) *crls)
 	{
 	X509_CRL *delta;
 	int i;
 	if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
 		return;
 	if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
 		return;
 	for (i = 0; i < sk_X509_CRL_num(crls); i++)
 		{
 		delta = sk_X509_CRL_value(crls, i);
 		if (check_delta_base(delta, base))
 			{
 			if (check_crl_time(ctx, delta, 0))
 				*pscore |= CRL_SCORE_TIME_DELTA;
 			CRYPTO_add(&delta->references, 1, CRYPTO_LOCK_X509_CRL);
 			*dcrl = delta;
 			return;
 			}
 		}
 	*dcrl = NULL;
 	}
 
 /* For a given CRL return how suitable it is for the supplied certificate 'x'.
  * The return value is a mask of several criteria.
  * If the issuer is not the certificate issuer this is returned in *pissuer.
  * The reasons mask is also used to determine if the CRL is suitable: if
  * no new reasons the CRL is rejected, otherwise reasons is updated.
  */
 
 static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
 			unsigned int *preasons,
 			X509_CRL *crl, X509 *x)
 	{
 
 	int crl_score = 0;
 	unsigned int tmp_reasons = *preasons, crl_reasons;
 
 	/* First see if we can reject CRL straight away */
 
 	/* Invalid IDP cannot be processed */
 	if (crl->idp_flags & IDP_INVALID)
 		return 0;
 	/* Reason codes or indirect CRLs need extended CRL support */
 	if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
 		{
 		if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
 			return 0;
 		}
 	else if (crl->idp_flags & IDP_REASONS)
 		{
 		/* If no new reasons reject */
 		if (!(crl->idp_reasons & ~tmp_reasons))
 			return 0;
 		}
 	/* Don't process deltas at this stage */
 	else if (crl->base_crl_number)
 		return 0;
 	/* If issuer name doesn't match certificate need indirect CRL */
 	if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)))
 		{
 		if (!(crl->idp_flags & IDP_INDIRECT))
 			return 0;
 		}
 	else
 		crl_score |= CRL_SCORE_ISSUER_NAME;
 
 	if (!(crl->flags & EXFLAG_CRITICAL))
 		crl_score |= CRL_SCORE_NOCRITICAL;
 
 	/* Check expiry */
 	if (check_crl_time(ctx, crl, 0))
 		crl_score |= CRL_SCORE_TIME;
 
 	/* Check authority key ID and locate certificate issuer */
 	crl_akid_check(ctx, crl, pissuer, &crl_score);
 
 	/* If we can't locate certificate issuer at this point forget it */
 
 	if (!(crl_score & CRL_SCORE_AKID))
 		return 0;
 
 	/* Check cert for matching CRL distribution points */
 
 	if (crl_crldp_check(x, crl, crl_score, &crl_reasons))
 		{
 		/* If no new reasons reject */
 		if (!(crl_reasons & ~tmp_reasons))
 			return 0;
 		tmp_reasons |= crl_reasons;
 		crl_score |= CRL_SCORE_SCOPE;
 		}
 
 	*preasons = tmp_reasons;
 
 	return crl_score;
 
 	}
 
 static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
 				X509 **pissuer, int *pcrl_score)
 	{
 	X509 *crl_issuer = NULL;
 	X509_NAME *cnm = X509_CRL_get_issuer(crl);
 	int cidx = ctx->error_depth;
 	int i;
 
 	if (cidx != sk_X509_num(ctx->chain) - 1)
 		cidx++;
 
 	crl_issuer = sk_X509_value(ctx->chain, cidx);
 
 	if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
 		{
 		if (*pcrl_score & CRL_SCORE_ISSUER_NAME)
 			{
 			*pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT;
 			*pissuer = crl_issuer;
 			return;
 			}
 		}
 
 	for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++)
 		{
 		crl_issuer = sk_X509_value(ctx->chain, cidx);
 		if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
 			continue;
 		if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
 			{
 			*pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH;
 			*pissuer = crl_issuer;
 			return;
 			}
 		}
 
 	/* Anything else needs extended CRL support */
 
 	if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
 		return;
 
 	/* Otherwise the CRL issuer is not on the path. Look for it in the
 	 * set of untrusted certificates.
 	 */
 	for (i = 0; i < sk_X509_num(ctx->untrusted); i++)
 		{
 		crl_issuer = sk_X509_value(ctx->untrusted, i);
 		if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
 			continue;
 		if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
 			{
 			*pissuer = crl_issuer;
 			*pcrl_score |= CRL_SCORE_AKID;
 			return;
 			}
 		}
 	}
 
 /* Check the path of a CRL issuer certificate. This creates a new
  * X509_STORE_CTX and populates it with most of the parameters from the
  * parent. This could be optimised somewhat since a lot of path checking
  * will be duplicated by the parent, but this will rarely be used in 
  * practice.
  */
 
 static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
 	{
 	X509_STORE_CTX crl_ctx;
 	int ret;
 	/* Don't allow recursive CRL path validation */
 	if (ctx->parent)
 		return 0;
 	if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
 		return -1;
 
 	crl_ctx.crls = ctx->crls;
 	/* Copy verify params across */
 	X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
 
 	crl_ctx.parent = ctx;
 	crl_ctx.verify_cb = ctx->verify_cb;
 
 	/* Verify CRL issuer */
 	ret = X509_verify_cert(&crl_ctx);
 
 	if (ret <= 0)
 		goto err;
 
 	/* Check chain is acceptable */
 
 	ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
 	err:
 	X509_STORE_CTX_cleanup(&crl_ctx);
 	return ret;
 	}
 
 /* RFC3280 says nothing about the relationship between CRL path
  * and certificate path, which could lead to situations where a
  * certificate could be revoked or validated by a CA not authorised
  * to do so. RFC5280 is more strict and states that the two paths must
  * end in the same trust anchor, though some discussions remain...
  * until this is resolved we use the RFC5280 version
  */
 
 static int check_crl_chain(X509_STORE_CTX *ctx,
 			STACK_OF(X509) *cert_path,
 			STACK_OF(X509) *crl_path)
 	{
 	X509 *cert_ta, *crl_ta;
 	cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
 	crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
 	if (!X509_cmp(cert_ta, crl_ta))
 		return 1;
 	return 0;
 	}
 
 /* Check for match between two dist point names: three separate cases.
  * 1. Both are relative names and compare X509_NAME types.
  * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
  * 3. Both are full names and compare two GENERAL_NAMES.
  * 4. One is NULL: automatic match.
  */
 
 
 static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
 	{
 	X509_NAME *nm = NULL;
 	GENERAL_NAMES *gens = NULL;
 	GENERAL_NAME *gena, *genb;
 	int i, j;
 	if (!a || !b)
 		return 1;
 	if (a->type == 1)
 		{
 		if (!a->dpname)
 			return 0;
 		/* Case 1: two X509_NAME */
 		if (b->type == 1)
 			{
 			if (!b->dpname)
 				return 0;
 			if (!X509_NAME_cmp(a->dpname, b->dpname))
 				return 1;
 			else
 				return 0;
 			}
 		/* Case 2: set name and GENERAL_NAMES appropriately */
 		nm = a->dpname;
 		gens = b->name.fullname;
 		}
 	else if (b->type == 1)
 		{
 		if (!b->dpname)
 			return 0;
 		/* Case 2: set name and GENERAL_NAMES appropriately */
 		gens = a->name.fullname;
 		nm = b->dpname;
 		}
 
 	/* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
 	if (nm)
 		{
 		for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
 			{
 			gena = sk_GENERAL_NAME_value(gens, i);	
 			if (gena->type != GEN_DIRNAME)
 				continue;
 			if (!X509_NAME_cmp(nm, gena->d.directoryName))
 				return 1;
 			}
 		return 0;
 		}
 
 	/* Else case 3: two GENERAL_NAMES */
 
 	for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++)
 		{
 		gena = sk_GENERAL_NAME_value(a->name.fullname, i);
 		for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++)
 			{
 			genb = sk_GENERAL_NAME_value(b->name.fullname, j);
 			if (!GENERAL_NAME_cmp(gena, genb))
 				return 1;
 			}
 		}
 
 	return 0;
 
 	}
 
 static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
 	{
 	int i;
 	X509_NAME *nm = X509_CRL_get_issuer(crl);
 	/* If no CRLissuer return is successful iff don't need a match */
 	if (!dp->CRLissuer)
 		return !!(crl_score & CRL_SCORE_ISSUER_NAME);
 	for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
 		{
 		GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
 		if (gen->type != GEN_DIRNAME)
 			continue;
 		if (!X509_NAME_cmp(gen->d.directoryName, nm))
 			return 1;
 		}
 	return 0;
 	}
 
 /* Check CRLDP and IDP */
 
 static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
 				unsigned int *preasons)
 	{
 	int i;
 	if (crl->idp_flags & IDP_ONLYATTR)
 		return 0;
 	if (x->ex_flags & EXFLAG_CA)
 		{
 		if (crl->idp_flags & IDP_ONLYUSER)
 			return 0;
 		}
 	else
 		{
 		if (crl->idp_flags & IDP_ONLYCA)
 			return 0;
 		}
 	*preasons = crl->idp_reasons;
 	for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
 		{
 		DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
 		if (crldp_check_crlissuer(dp, crl, crl_score))
 			{
 			if (!crl->idp ||
 			     idp_check_dp(dp->distpoint, crl->idp->distpoint))
 				{
 				*preasons &= dp->dp_reasons;
 				return 1;
 				}
 			}
 		}
 	if ((!crl->idp || !crl->idp->distpoint) && (crl_score & CRL_SCORE_ISSUER_NAME))
 		return 1;
 	return 0;
 	}
 
 /* Retrieve CRL corresponding to current certificate.
  * If deltas enabled try to find a delta CRL too
  */
 	
 static int get_crl_delta(X509_STORE_CTX *ctx,
 				X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
 	{
 	int ok;
 	X509 *issuer = NULL;
 	int crl_score = 0;
 	unsigned int reasons;
 	X509_CRL *crl = NULL, *dcrl = NULL;
 	STACK_OF(X509_CRL) *skcrl;
 	X509_NAME *nm = X509_get_issuer_name(x);
 	reasons = ctx->current_reasons;
 	ok = get_crl_sk(ctx, &crl, &dcrl, 
 				&issuer, &crl_score, &reasons, ctx->crls);
 
 	if (ok)
 		goto done;
 
 	/* Lookup CRLs from store */
 
 	skcrl = ctx->lookup_crls(ctx, nm);
 
 	/* If no CRLs found and a near match from get_crl_sk use that */
 	if (!skcrl && crl)
 		goto done;
 
 	get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
 
 	sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
 
 	done:
 
 	/* If we got any kind of CRL use it and return success */
 	if (crl)
 		{
 		ctx->current_issuer = issuer;
 		ctx->current_crl_score = crl_score;
 		ctx->current_reasons = reasons;
 		*pcrl = crl;
 		*pdcrl = dcrl;
 		return 1;
 		}
 
 	return 0;
 	}
 
 /* Check CRL validity */
 static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
 	{
 	X509 *issuer = NULL;
 	EVP_PKEY *ikey = NULL;
 	int ok = 0, chnum, cnum;
 	cnum = ctx->error_depth;
 	chnum = sk_X509_num(ctx->chain) - 1;
 	/* if we have an alternative CRL issuer cert use that */
 	if (ctx->current_issuer)
 		issuer = ctx->current_issuer;
 
 	/* Else find CRL issuer: if not last certificate then issuer
 	 * is next certificate in chain.
 	 */
 	else if (cnum < chnum)
 		issuer = sk_X509_value(ctx->chain, cnum + 1);
 	else
 		{
 		issuer = sk_X509_value(ctx->chain, chnum);
 		/* If not self signed, can't check signature */
 		if(!ctx->check_issued(ctx, issuer, issuer))
 			{
 			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) goto err;
 			}
 		}
 
 	if(issuer)
 		{
 		/* Skip most tests for deltas because they have already
 		 * been done
 		 */
 		if (!crl->base_crl_number)
 			{
 			/* Check for cRLSign bit if keyUsage present */
 			if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
 				!(issuer->ex_kusage & KU_CRL_SIGN))
 				{
 				ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
 				ok = ctx->verify_cb(0, ctx);
 				if(!ok) goto err;
 				}
 
 			if (!(ctx->current_crl_score & CRL_SCORE_SCOPE))
 				{
 				ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
 				ok = ctx->verify_cb(0, ctx);
 				if(!ok) goto err;
 				}
 
 			if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
 				{
 				if (check_crl_path(ctx, ctx->current_issuer) <= 0)
 					{
 					ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
 					ok = ctx->verify_cb(0, ctx);
 					if(!ok) goto err;
 					}
 				}
 
 			if (crl->idp_flags & IDP_INVALID)
 				{
 				ctx->error = X509_V_ERR_INVALID_EXTENSION;
 				ok = ctx->verify_cb(0, ctx);
 				if(!ok) goto err;
 				}
 
 
 			}
 
 		if (!(ctx->current_crl_score & CRL_SCORE_TIME))
 			{
 			ok = check_crl_time(ctx, crl, 1);
 			if (!ok)
 				goto err;
 			}
 
 		/* Attempt to get issuer certificate public key */
 		ikey = X509_get_pubkey(issuer);
 
 		if(!ikey)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 			ok = ctx->verify_cb(0, ctx);
 			if (!ok) goto err;
 			}
 		else
 			{
 			/* Verify CRL signature */
 			if(X509_CRL_verify(crl, ikey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
 				ok = ctx->verify_cb(0, ctx);
 				if (!ok) goto err;
 				}
 			}
 		}
 
 	ok = 1;
 
 	err:
 	EVP_PKEY_free(ikey);
 	return ok;
 	}
 
 /* Check certificate against CRL */
 static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 	{
 	int ok;
 	X509_REVOKED *rev;
 	/* The rules changed for this... previously if a CRL contained
 	 * unhandled critical extensions it could still be used to indicate
 	 * a certificate was revoked. This has since been changed since 
 	 * critical extension can change the meaning of CRL entries.
 	 */
 	if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 		&& (crl->flags & EXFLAG_CRITICAL))
 		{
 		ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
 		ok = ctx->verify_cb(0, ctx);
 		if(!ok)
 			return 0;
 		}
 	/* Look for serial number of certificate in CRL
 	 * If found make sure reason is not removeFromCRL.
 	 */
 	if (X509_CRL_get0_by_cert(crl, &rev, x))
 		{
 		if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
 			return 2;
 		ctx->error = X509_V_ERR_CERT_REVOKED;
 		ok = ctx->verify_cb(0, ctx);
 		if (!ok)
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int check_policy(X509_STORE_CTX *ctx)
 	{
 	int ret;
 	if (ctx->parent)
 		return 1;
 	ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
 				ctx->param->policies, ctx->param->flags);
 	if (ret == 0)
 		{
 		X509err(X509_F_CHECK_POLICY,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	/* Invalid or inconsistent extensions */
 	if (ret == -1)
 		{
 		/* Locate certificates with bad extensions and notify
 		 * callback.
 		 */
 		X509 *x;
 		int i;
 		for (i = 1; i < sk_X509_num(ctx->chain); i++)
 			{
 			x = sk_X509_value(ctx->chain, i);
 			if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
 				continue;
 			ctx->current_cert = x;
 			ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
 			if(!ctx->verify_cb(0, ctx))
 				return 0;
 			}
 		return 1;
 		}
 	if (ret == -2)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
 		return ctx->verify_cb(0, ctx);
 		}
 
 	if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_OK;
 		if (!ctx->verify_cb(2, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
 	{
 	time_t *ptime;
 	int i;
 
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_get_notBefore(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	i=X509_cmp_time(X509_get_notAfter(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i < 0)
 		{
 		ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int internal_verify(X509_STORE_CTX *ctx)
 	{
 	int ok=0,n;
 	X509 *xs,*xi;
 	EVP_PKEY *pkey=NULL;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 
 	cb=ctx->verify_cb;
 
 	n=sk_X509_num(ctx->chain);
 	ctx->error_depth=n-1;
 	n--;
 	xi=sk_X509_value(ctx->chain,n);
 
 	if (ctx->check_issued(ctx, xi, xi))
 		xs=xi;
 	else
 		{
 		if (n <= 0)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
 			ctx->current_cert=xi;
 			ok=cb(0,ctx);
 			goto end;
 			}
 		else
 			{
 			n--;
 			ctx->error_depth=n;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 
 /*	ctx->error=0;  not needed */
 	while (n >= 0)
 		{
 		ctx->error_depth=n;
 
 		/* Skip signature check for self signed certificates unless
 		 * explicitly asked for. It doesn't add any security and
 		 * just wastes time.
 		 */
 		if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
 			{
 			if ((pkey=X509_get_pubkey(xi)) == NULL)
 				{
 				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 				ctx->current_cert=xi;
 				ok=(*cb)(0,ctx);
 				if (!ok) goto end;
 				}
 			else if (X509_verify(xs,pkey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
 				ctx->current_cert=xs;
 				ok=(*cb)(0,ctx);
 				if (!ok)
 					{
 					EVP_PKEY_free(pkey);
 					goto end;
 					}
 				}
 			EVP_PKEY_free(pkey);
 			pkey=NULL;
 			}
 
 		xs->valid = 1;
 
 		ok = check_cert_time(ctx, xs);
 		if (!ok)
 			goto end;
 
 		/* The last error (if any) is still in the error value */
 		ctx->current_issuer=xi;
 		ctx->current_cert=xs;
 		ok=(*cb)(1,ctx);
 		if (!ok) goto end;
 
 		n--;
 		if (n >= 0)
 			{
 			xi=xs;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 	ok=1;
 end:
 	return ok;
 	}
 
 int X509_cmp_current_time(const ASN1_TIME *ctm)
 {
 	return X509_cmp_time(ctm, NULL);
 }
 
 int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
-	{
+{
 	char *str;
 	ASN1_TIME atm;
 	long offset;
-	char buff1[24],buff2[24],*p;
-	int i,j;
+    char buff1[24], buff2[24], *p;
+    int i, j, remaining;
 
-	p=buff1;
-	i=ctm->length;
-	str=(char *)ctm->data;
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		if ((i < 11) || (i > 17)) return 0;
-		memcpy(p,str,10);
-		p+=10;
-		str+=10;
+    p = buff1;
+    remaining = ctm->length;
+    str = (char *)ctm->data;
+    /*
+     * Note that the following (historical) code allows much more slack in the
+     * time format than RFC5280. In RFC5280, the representation is fixed:
+     * UTCTime: YYMMDDHHMMSSZ
+     * GeneralizedTime: YYYYMMDDHHMMSSZ
+     */
+    if (ctm->type == V_ASN1_UTCTIME) {
+        /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+        int min_length = sizeof("YYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 10);
+        p += 10;
+        str += 10;
+        remaining -= 10;
+    } else {
+        /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
+        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 12);
+        p += 12;
+        str += 12;
+        remaining -= 12;
 		}
-	else
-		{
-		if (i < 13) return 0;
-		memcpy(p,str,12);
-		p+=12;
-		str+=12;
-		}
 
-	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
-		{ *(p++)='0'; *(p++)='0'; }
-	else
-		{ 
-		*(p++)= *(str++);
-		*(p++)= *(str++);
-		/* Skip any fractional seconds... */
-		if (*str == '.')
-			{
+    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+        *(p++) = '0';
+        *(p++) = '0';
+    } else {
+        /* SS (seconds) */
+        if (remaining < 2)
+            return 0;
+        *(p++) = *(str++);
+        *(p++) = *(str++);
+        remaining -= 2;
+        /*
+         * Skip any (up to three) fractional seconds...
+         * TODO(emilia): in RFC5280, fractional seconds are forbidden.
+         * Can we just kill them altogether?
+         */
+        if (remaining && *str == '.') {
 			str++;
-			while ((*str >= '0') && (*str <= '9')) str++;
+            remaining--;
+            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+                if (*str < '0' || *str > '9')
+                    break;
 			}
-		
 		}
-	*(p++)='Z';
-	*(p++)='\0';
 
-	if (*str == 'Z')
-		offset=0;
-	else
-		{
+    }
+    *(p++) = 'Z';
+    *(p++) = '\0';
+
+    /* We now need either a terminating 'Z' or an offset. */
+    if (!remaining)
+        return 0;
+    if (*str == 'Z') {
+        if (remaining != 1)
+            return 0;
+        offset = 0;
+    } else {
+        /* (+-)HHMM */
 		if ((*str != '+') && (*str != '-'))
 			return 0;
-		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
-		offset+=(str[3]-'0')*10+(str[4]-'0');
+        /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
+        if (remaining != 5)
+            return 0;
+        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+            return 0;
+        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+        offset += (str[3] - '0') * 10 + (str[4] - '0');
 		if (*str == '-')
-			offset= -offset;
+            offset = -offset;
 		}
-	atm.type=ctm->type;
+    atm.type = ctm->type;
 	atm.flags = 0;
-	atm.length=sizeof(buff2);
-	atm.data=(unsigned char *)buff2;
+    atm.length = sizeof(buff2);
+    atm.data = (unsigned char *)buff2;
 
-	if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
 		return 0;
 
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		i=(buff1[0]-'0')*10+(buff1[1]-'0');
-		if (i < 50) i+=100; /* cf. RFC 2459 */
-		j=(buff2[0]-'0')*10+(buff2[1]-'0');
-		if (j < 50) j+=100;
+    if (ctm->type == V_ASN1_UTCTIME) {
+        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+        if (i < 50)
+            i += 100;           /* cf. RFC 2459 */
+        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+        if (j < 50)
+            j += 100;
 
-		if (i < j) return -1;
-		if (i > j) return 1;
+        if (i < j)
+            return -1;
+        if (i > j)
+            return 1;
 		}
-	i=strcmp(buff1,buff2);
+    i = strcmp(buff1, buff2);
 	if (i == 0) /* wait a second then return younger :-) */
 		return -1;
 	else
 		return i;
-	}
+}
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
 	return X509_time_adj(s, adj, NULL);
 }
 
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
 	{
 	return X509_time_adj_ex(s, 0, offset_sec, in_tm);
 	}
 
 ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
 				int offset_day, long offset_sec, time_t *in_tm)
 	{
 	time_t t;
 
 	if (in_tm) t = *in_tm;
 	else time(&t);
 
 	if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
 		{
 		if (s->type == V_ASN1_UTCTIME)
 			return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
 		if (s->type == V_ASN1_GENERALIZEDTIME)
 			return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
 								offset_sec);
 		}
 	return ASN1_TIME_adj(s, t, offset_day, offset_sec);
 	}
 
 int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
 	{
 	EVP_PKEY *ktmp=NULL,*ktmp2;
 	int i,j;
 
 	if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
 
 	for (i=0; i= 0; j--)
 		{
 		ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
 		EVP_PKEY_copy_parameters(ktmp2,ktmp);
 		EVP_PKEY_free(ktmp2);
 		}
 	
 	if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
 	EVP_PKEY_free(ktmp);
 	return 1;
 	}
 
 int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	/* This function is (usually) called only once, by
 	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
 	{
 	return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
 	}
 
 void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
 	{
 	return CRYPTO_get_ex_data(&ctx->ex_data,idx);
 	}
 
 int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
 	{
 	return ctx->error;
 	}
 
 void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
 	{
 	ctx->error=err;
 	}
 
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
 	{
 	return ctx->error_depth;
 	}
 
 X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
 	{
 	return ctx->current_cert;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
 	{
 	return ctx->chain;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
 	{
 	int i;
 	X509 *x;
 	STACK_OF(X509) *chain;
 	if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL;
 	for (i = 0; i < sk_X509_num(chain); i++)
 		{
 		x = sk_X509_value(chain, i);
 		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
 		}
 	return chain;
 	}
 
 X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
 	{
 	return ctx->current_issuer;
 	}
 
 X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
 	{
 	return ctx->current_crl;
 	}
 
 X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
 	{
 	return ctx->parent;
 	}
 
 void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
 	{
 	ctx->cert=x;
 	}
 
 void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 	{
 	ctx->untrusted=sk;
 	}
 
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 	{
 	ctx->crls=sk;
 	}
 
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
 	}
 
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
 	}
 
 /* This function is used to set the X509_STORE_CTX purpose and trust
  * values. This is intended to be used when another structure has its
  * own trust and purpose values which (if set) will be inherited by
  * the ctx. If they aren't set then we will usually have a default
  * purpose in mind which should then be used to set the trust value.
  * An example of this is SSL use: an SSL structure will have its own
  * purpose and trust settings which the application can set: if they
  * aren't set then we use the default of SSL client/server.
  */
 
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
 				int purpose, int trust)
 {
 	int idx;
 	/* If purpose not set use default */
 	if (!purpose) purpose = def_purpose;
 	/* If we have a purpose then check it is valid */
 	if (purpose)
 		{
 		X509_PURPOSE *ptmp;
 		idx = X509_PURPOSE_get_by_id(purpose);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 			return 0;
 			}
 		ptmp = X509_PURPOSE_get0(idx);
 		if (ptmp->trust == X509_TRUST_DEFAULT)
 			{
 			idx = X509_PURPOSE_get_by_id(def_purpose);
 			if (idx == -1)
 				{
 				X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 				return 0;
 				}
 			ptmp = X509_PURPOSE_get0(idx);
 			}
 		/* If trust not set then get from purpose default */
 		if (!trust) trust = ptmp->trust;
 		}
 	if (trust)
 		{
 		idx = X509_TRUST_get_by_id(trust);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_TRUST_ID);
 			return 0;
 			}
 		}
 
 	if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
 	if (trust && !ctx->param->trust) ctx->param->trust = trust;
 	return 1;
 }
 
 X509_STORE_CTX *X509_STORE_CTX_new(void)
 {
 	X509_STORE_CTX *ctx;
 	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
 	if (!ctx)
 		{
 		X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 	memset(ctx, 0, sizeof(X509_STORE_CTX));
 	return ctx;
 }
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
 	X509_STORE_CTX_cleanup(ctx);
 	OPENSSL_free(ctx);
 }
 
 int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
 	     STACK_OF(X509) *chain)
 	{
 	int ret = 1;
 	ctx->ctx=store;
 	ctx->current_method=0;
 	ctx->cert=x509;
 	ctx->untrusted=chain;
 	ctx->crls = NULL;
 	ctx->last_untrusted=0;
 	ctx->other_ctx=NULL;
 	ctx->valid=0;
 	ctx->chain=NULL;
 	ctx->error=0;
 	ctx->explicit_policy=0;
 	ctx->error_depth=0;
 	ctx->current_cert=NULL;
 	ctx->current_issuer=NULL;
 	ctx->current_crl=NULL;
 	ctx->current_crl_score=0;
 	ctx->current_reasons=0;
 	ctx->tree = NULL;
 	ctx->parent = NULL;
 
 	ctx->param = X509_VERIFY_PARAM_new();
 
 	if (!ctx->param)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	/* Inherit callbacks and flags from X509_STORE if not set
 	 * use defaults.
 	 */
 
 
 	if (store)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
 	else
 		ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
 
 	if (store)
 		{
 		ctx->verify_cb = store->verify_cb;
 		ctx->cleanup = store->cleanup;
 		}
 	else
 		ctx->cleanup = 0;
 
 	if (ret)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param,
 					X509_VERIFY_PARAM_lookup("default"));
 
 	if (ret == 0)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	if (store && store->check_issued)
 		ctx->check_issued = store->check_issued;
 	else
 		ctx->check_issued = check_issued;
 
 	if (store && store->get_issuer)
 		ctx->get_issuer = store->get_issuer;
 	else
 		ctx->get_issuer = X509_STORE_CTX_get1_issuer;
 
 	if (store && store->verify_cb)
 		ctx->verify_cb = store->verify_cb;
 	else
 		ctx->verify_cb = null_callback;
 
 	if (store && store->verify)
 		ctx->verify = store->verify;
 	else
 		ctx->verify = internal_verify;
 
 	if (store && store->check_revocation)
 		ctx->check_revocation = store->check_revocation;
 	else
 		ctx->check_revocation = check_revocation;
 
 	if (store && store->get_crl)
 		ctx->get_crl = store->get_crl;
 	else
 		ctx->get_crl = NULL;
 
 	if (store && store->check_crl)
 		ctx->check_crl = store->check_crl;
 	else
 		ctx->check_crl = check_crl;
 
 	if (store && store->cert_crl)
 		ctx->cert_crl = store->cert_crl;
 	else
 		ctx->cert_crl = cert_crl;
 
 	if (store && store->lookup_certs)
 		ctx->lookup_certs = store->lookup_certs;
 	else
 		ctx->lookup_certs = X509_STORE_get1_certs;
 
 	if (store && store->lookup_crls)
 		ctx->lookup_crls = store->lookup_crls;
 	else
 		ctx->lookup_crls = X509_STORE_get1_crls;
 
 	ctx->check_policy = check_policy;
 
 
 	/* This memset() can't make any sense anyway, so it's removed. As
 	 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
 	 * corresponding "new" here and remove this bogus initialisation. */
 	/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
 	if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
 				&(ctx->ex_data)))
 		{
 		OPENSSL_free(ctx);
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	return 1;
 	}
 
 /* Set alternative lookup method: just a STACK of trusted certificates.
  * This avoids X509_STORE nastiness where it isn't needed.
  */
 
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
 	ctx->other_ctx = sk;
 	ctx->get_issuer = get_issuer_sk;
 }
 
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
 	{
 	if (ctx->cleanup) ctx->cleanup(ctx);
 	if (ctx->param != NULL)
 		{
 		if (ctx->parent == NULL)
 			X509_VERIFY_PARAM_free(ctx->param);
 		ctx->param=NULL;
 		}
 	if (ctx->tree != NULL)
 		{
 		X509_policy_tree_free(ctx->tree);
 		ctx->tree=NULL;
 		}
 	if (ctx->chain != NULL)
 		{
 		sk_X509_pop_free(ctx->chain,X509_free);
 		ctx->chain=NULL;
 		}
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
 	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
 	}
 
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
 	{
 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
 	}
 
 void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
 	{
 	X509_VERIFY_PARAM_set_flags(ctx->param, flags);
 	}
 
 void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
 	{
 	X509_VERIFY_PARAM_set_time(ctx->param, t);
 	}
 
 void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
 				  int (*verify_cb)(int, X509_STORE_CTX *))
 	{
 	ctx->verify_cb=verify_cb;
 	}
 
 X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
 	{
 	return ctx->tree;
 	}
 
 int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
 	{
 	return ctx->explicit_policy;
 	}
 
 int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
 	{
 	const X509_VERIFY_PARAM *param;
 	param = X509_VERIFY_PARAM_lookup(name);
 	if (!param)
 		return 0;
 	return X509_VERIFY_PARAM_inherit(ctx->param, param);
 	}
 
 X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
 	{
 	return ctx->param;
 	}
 
 void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
 	{
 	if (ctx->param)
 		X509_VERIFY_PARAM_free(ctx->param);
 	ctx->param = param;
 	}
 
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)
 
 IMPLEMENT_STACK_OF(X509_NAME)
 
 IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
 IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
Index: releng/10.1/crypto/openssl/crypto/x509/x509type.c
===================================================================
--- releng/10.1/crypto/openssl/crypto/x509/x509type.c	(revision 284294)
+++ releng/10.1/crypto/openssl/crypto/x509/x509type.c	(revision 284295)
@@ -1,131 +1,128 @@
 /* crypto/x509/x509type.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 
 int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
 	{
 	EVP_PKEY *pk;
 	int ret=0,i;
 
 	if (x == NULL) return(0);
 
 	if (pkey == NULL)
 		pk=X509_get_pubkey(x);
 	else
 		pk=pkey;
 
 	if (pk == NULL) return(0);
 
 	switch (pk->type)
 		{
 	case EVP_PKEY_RSA:
 		ret=EVP_PK_RSA|EVP_PKT_SIGN;
 /*		if (!sign only extension) */
 			ret|=EVP_PKT_ENC;
 	break;
 	case EVP_PKEY_DSA:
 		ret=EVP_PK_DSA|EVP_PKT_SIGN;
 		break;
 	case EVP_PKEY_EC:
 		ret=EVP_PK_EC|EVP_PKT_SIGN|EVP_PKT_EXCH;
 		break;
 	case EVP_PKEY_DH:
 		ret=EVP_PK_DH|EVP_PKT_EXCH;
 		break;	
 	case NID_id_GostR3410_94:
 	case NID_id_GostR3410_2001:
 		ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
 		break;
 	default:
 		break;
 		}
 
 	i=OBJ_obj2nid(x->sig_alg->algorithm);
 	if (i && OBJ_find_sigid_algs(i, NULL, &i))
 		{
 
 		switch (i)
 			{
 		case NID_rsaEncryption:
 		case NID_rsa:
 			ret|=EVP_PKS_RSA;
 			break;
 		case NID_dsa:
 		case NID_dsa_2:
 			ret|=EVP_PKS_DSA;
 			break;
 		case NID_X9_62_id_ecPublicKey:
 			ret|=EVP_PKS_EC;
 			break;
 		default:
 			break;
 			}
 		}
 
-	if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look
-					   for, not bytes */
-		ret|=EVP_PKT_EXP;
 	if(pkey==NULL) EVP_PKEY_free(pk);
 	return(ret);
 	}
 
Index: releng/10.1/crypto/openssl/doc/apps/dhparam.pod
===================================================================
--- releng/10.1/crypto/openssl/doc/apps/dhparam.pod	(revision 284294)
+++ releng/10.1/crypto/openssl/doc/apps/dhparam.pod	(revision 284295)
@@ -1,146 +1,149 @@
 =pod
 
 =head1 NAME
 
 dhparam - DH parameter manipulation and generation
 
 =head1 SYNOPSIS
 
 B
 [B<-inform DER|PEM>]
 [B<-outform DER|PEM>]
 [B<-in> I]
 [B<-out> I]
 [B<-dsaparam>]
 [B<-check>]
 [B<-noout>]
 [B<-text>]
 [B<-C>]
 [B<-2>]
 [B<-5>]
 [B<-rand> I]
 [B<-engine id>]
 [I]
 
 =head1 DESCRIPTION
 
 This command is used to manipulate DH parameter files.
 
 =head1 OPTIONS
 
 =over 4
 
 =item B<-inform DER|PEM>
 
 This specifies the input format. The B option uses an ASN1 DER encoded
 form compatible with the PKCS#3 DHparameter structure. The PEM form is the
 default format: it consists of the B format base64 encoded with
 additional header and footer lines.
 
 =item B<-outform DER|PEM>
 
 This specifies the output format, the options have the same meaning as the 
 B<-inform> option.
 
 =item B<-in> I
 
 This specifies the input filename to read parameters from or standard input if
 this option is not specified.
 
 =item B<-out> I
 
 This specifies the output filename parameters to. Standard output is used
 if this option is not present. The output filename should B be the same
 as the input filename.
 
 =item B<-dsaparam>
 
 If this option is used, DSA rather than DH parameters are read or created;
 they are converted to DH format.  Otherwise, "strong" primes (such
 that (p-1)/2 is also prime) will be used for DH parameter generation.
 
 DH parameter generation with the B<-dsaparam> option is much faster,
 and the recommended exponent length is shorter, which makes DH key
 exchange more efficient.  Beware that with such DSA-style DH
 parameters, a fresh DH key should be created for each use to
 avoid small-subgroup attacks that may be possible otherwise.
 
 =item B<-check>
 
 check if the parameters are valid primes and generator.
 
 =item B<-2>, B<-5>
 
-The generator to use, either 2 or 5. 2 is the default. If present then the
-input file is ignored and parameters are generated instead.
+The generator to use, either 2 or 5. If present then the
+input file is ignored and parameters are generated instead. If not
+present but B is present, parameters are generated with the
+default generator 2.
 
 =item B<-rand> I
 
 a file or files containing random data used to seed the random number
 generator, or an EGD socket (see L).
 Multiple files can be specified separated by a OS-dependent character.
 The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
 all others.
 
 =item I
 
 this option specifies that a parameter set should be generated of size
-I. It must be the last option. If not present then a value of 512
-is used. If this option is present then the input file is ignored and 
-parameters are generated instead.
+I. It must be the last option. If this option is present then
+the input file is ignored and parameters are generated instead. If
+this option is not present but a generator (B<-2> or B<-5>) is
+present, parameters are generated with a default length of 2048 bits.
 
 =item B<-noout>
 
 this option inhibits the output of the encoded version of the parameters.
 
 =item B<-text>
 
 this option prints out the DH parameters in human readable form.
 
 =item B<-C>
 
 this option converts the parameters into C code. The parameters can then
 be loaded by calling the BIB<()> function.
 
 =item B<-engine id>
 
 specifying an engine (by its unique B string) will cause B
 to attempt to obtain a functional reference to the specified engine,
 thus initialising it if needed. The engine will then be set as the default
 for all available algorithms.
 
 =back
 
 =head1 WARNINGS
 
 The program B combines the functionality of the programs B and
 B in previous versions of OpenSSL and SSLeay. The B and B
 programs are retained for now but may have different purposes in future 
 versions of OpenSSL.
 
 =head1 NOTES
 
 PEM format DH parameters use the header and footer lines:
 
  -----BEGIN DH PARAMETERS-----
  -----END DH PARAMETERS-----
 
 OpenSSL currently only supports the older PKCS#3 DH, not the newer X9.42
 DH.
 
 This program manipulates DH parameters not keys.
 
 =head1 BUGS
 
 There should be a way to generate and manipulate DH keys.
 
 =head1 SEE ALSO
 
 L
 
 =head1 HISTORY
 
 The B command was added in OpenSSL 0.9.5.
 The B<-dsaparam> option was added in OpenSSL 0.9.6.
 
 =cut
Index: releng/10.1/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
===================================================================
--- releng/10.1/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod	(revision 284294)
+++ releng/10.1/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod	(revision 284295)
@@ -1,169 +1,149 @@
 =pod
 
 =head1 NAME
 
 SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh, SSL_set_tmp_dh_callback, SSL_set_tmp_dh - handle DH keys for ephemeral key exchange
 
 =head1 SYNOPSIS
 
  #include 
 
  void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
             DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength));
  long SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
 
  void SSL_set_tmp_dh_callback(SSL *ctx,
             DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength));
  long SSL_set_tmp_dh(SSL *ssl, DH *dh)
 
 =head1 DESCRIPTION
 
 SSL_CTX_set_tmp_dh_callback() sets the callback function for B to be
 used when a DH parameters are required to B.
 The callback is inherited by all B objects created from B.
 
 SSL_CTX_set_tmp_dh() sets DH parameters to be used to be B.
 The key is inherited by all B objects created from B.
 
 SSL_set_tmp_dh_callback() sets the callback only for B.
 
 SSL_set_tmp_dh() sets the parameters only for B.
 
 These functions apply to SSL/TLS servers only.
 
 =head1 NOTES
 
 When using a cipher with RSA authentication, an ephemeral DH key exchange
 can take place. Ciphers with DSA keys always use ephemeral DH keys as well.
 In these cases, the session data are negotiated using the
 ephemeral/temporary DH key and the key supplied and certified
 by the certificate chain is only used for signing.
 Anonymous ciphers (without a permanent server key) also use ephemeral DH keys.
 
 Using ephemeral DH key exchange yields forward secrecy, as the connection
 can only be decrypted, when the DH key is known. By generating a temporary
 DH key inside the server application that is lost when the application
 is left, it becomes impossible for an attacker to decrypt past sessions,
 even if he gets hold of the normal (certified) key, as this key was
 only used for signing.
 
 In order to perform a DH key exchange the server must use a DH group
 (DH parameters) and generate a DH key.
 The server will always generate a new DH key during the negotiation
 if either the DH parameters are supplied via callback or the
 SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set (or both).
 It will  immediately create a DH key if DH parameters are supplied via
 SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set.
 In this case,
 it may happen that a key is generated on initialization without later
 being needed, while on the other hand the computer time during the
 negotiation is being saved.
 
 If "strong" primes were used to generate the DH parameters, it is not strictly
 necessary to generate a new key for each handshake but it does improve forward
-secrecy. If it is not assured, that "strong" primes were used (see especially
-the section about DSA parameters below), SSL_OP_SINGLE_DH_USE must be used
-in order to prevent small subgroup attacks. Always using SSL_OP_SINGLE_DH_USE
-has an impact on the computer time needed during negotiation, but it is not
-very large, so application authors/users should consider to always enable
-this option.
+secrecy. If it is not assured that "strong" primes were used,
+SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup
+attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the
+computer time needed during negotiation, but it is not very large, so
+application authors/users should consider always enabling this option.
+The option is required to implement perfect forward secrecy (PFS).
 
 As generating DH parameters is extremely time consuming, an application
 should not generate the parameters on the fly but supply the parameters.
 DH parameters can be reused, as the actual key is newly generated during
 the negotiation. The risk in reusing DH parameters is that an attacker
 may specialize on a very often used DH group. Applications should therefore
 generate their own DH parameters during the installation process using the
-openssl L application. In order to reduce the computer
-time needed for this generation, it is possible to use DSA parameters
-instead (see L), but in this case SSL_OP_SINGLE_DH_USE
-is mandatory.
+openssl L application. This application
+guarantees that "strong" primes are used.
 
-Application authors may compile in DH parameters. Files dh512.pem,
-dh1024.pem, dh2048.pem, and dh4096.pem in the 'apps' directory of current
+Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current
 version of the OpenSSL distribution contain the 'SKIP' DH parameters,
 which use safe primes and were generated verifiably pseudo-randomly.
 These files can be converted into C code using the B<-C> option of the
-L application.
-Authors may also generate their own set of parameters using
-L, but a user may not be sure how the parameters were
-generated. The generation of DH parameters during installation is therefore
-recommended.
+L application. Generation of custom DH
+parameters during installation should still be preferred to stop an
+attacker from specializing on a commonly used group. Files dh1024.pem
+and dh512.pem contain old parameters that must not be used by
+applications.
 
 An application may either directly specify the DH parameters or
-can supply the DH parameters via a callback function. The callback approach
-has the advantage, that the callback may supply DH parameters for different
-key lengths.
+can supply the DH parameters via a callback function.
 
-The B is called with the B needed and
-the B information. The B flag is set, when the
-ephemeral DH key exchange is performed with an export cipher.
+Previous versions of the callback used B and B
+parameters to control parameter generation for export and non-export
+cipher suites. Modern servers that do not support export ciphersuites
+are advised to either use SSL_CTX_set_tmp_dh() in combination with
+SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore
+B and B and simply supply at least 2048-bit
+parameters in the callback.
 
 =head1 EXAMPLES
 
-Handle DH parameters for key lengths of 512 and 1024 bits. (Error handling
+Setup DH parameters with a key length of 2048 bits. (Error handling
 partly left out.)
 
- ...
- /* Set up ephemeral DH stuff */
- DH *dh_512 = NULL;
- DH *dh_1024 = NULL;
- FILE *paramfile;
+ Command-line parameter generation:
+ $ openssl dhparam -out dh_param_2048.pem 2048
 
+ Code for setting up parameters during server initialization:
+
  ...
- /* "openssl dhparam -out dh_param_512.pem -2 512" */
- paramfile = fopen("dh_param_512.pem", "r");
+ SSL_CTX ctx = SSL_CTX_new();
+ ...
+
+ /* Set up ephemeral DH parameters. */
+ DH *dh_2048 = NULL;
+ FILE *paramfile;
+ paramfile = fopen("dh_param_2048.pem", "r");
  if (paramfile) {
-   dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
+   dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
    fclose(paramfile);
+ } else {
+   /* Error. */
  }
- /* "openssl dhparam -out dh_param_1024.pem -2 1024" */
- paramfile = fopen("dh_param_1024.pem", "r");
- if (paramfile) {
-   dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
-   fclose(paramfile);
+ if (dh_2048 == NULL) {
+  /* Error. */
  }
- ...
-
- /* "openssl dhparam -C -2 512" etc... */
- DH *get_dh512() { ... }
- DH *get_dh1024() { ... }
-
- DH *tmp_dh_callback(SSL *s, int is_export, int keylength)
- {
-    DH *dh_tmp=NULL;
-
-    switch (keylength) {
-    case 512:
-      if (!dh_512)
-        dh_512 = get_dh512();
-      dh_tmp = dh_512;
-      break;
-    case 1024:
-      if (!dh_1024)
-        dh_1024 = get_dh1024();
-      dh_tmp = dh_1024;
-      break;
-    default:
-      /* Generating a key on the fly is very costly, so use what is there */
-      setup_dh_parameters_like_above();
-    }
-    return(dh_tmp);
+ if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) {
+   /* Error. */
  }
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
+ ...
 
 =head1 RETURN VALUES
 
 SSL_CTX_set_tmp_dh_callback() and SSL_set_tmp_dh_callback() do not return
 diagnostic output.
 
 SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do return 1 on success and 0
 on failure. Check the error queue to find out the reason of failure.
 
 =head1 SEE ALSO
 
 L, L,
 L,
 L,
 L, L
 
 =cut
Index: releng/10.1/crypto/openssl/ssl/d1_both.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/d1_both.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/d1_both.c	(revision 284295)
@@ -1,1662 +1,1679 @@
 /* ssl/d1_both.c */
 /* 
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #include "ssl_locl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 
 #define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
 
 #define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
 			if ((end) - (start) <= 8) { \
 				long ii; \
 				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
 			} else { \
 				long ii; \
 				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
 				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
 				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
 			} }
 
 #define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
 			long ii; \
 			OPENSSL_assert((msg_len) > 0); \
 			is_complete = 1; \
 			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
 			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
 				if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
 
 #if 0
 #define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
 			long ii; \
 			printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
 			printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
 			printf("\n"); }
 #endif
 
 static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
 static unsigned char bitmask_end_values[]   = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
 
 /* XDTLS:  figure out the right values */
 static const unsigned int g_probable_mtu[] = {1500, 512, 256};
 
 static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, 
 	unsigned long frag_len);
 static unsigned char *dtls1_write_message_header(SSL *s,
 	unsigned char *p);
 static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
 	unsigned long len, unsigned short seq_num, unsigned long frag_off, 
 	unsigned long frag_len);
 static long dtls1_get_message_fragment(SSL *s, int st1, int stn, 
 	long max, int *ok);
 
 static hm_fragment *
 dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
 	{
 	hm_fragment *frag = NULL;
 	unsigned char *buf = NULL;
 	unsigned char *bitmask = NULL;
 
 	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
 	if ( frag == NULL)
 		return NULL;
 
 	if (frag_len)
 		{
 		buf = (unsigned char *)OPENSSL_malloc(frag_len);
 		if ( buf == NULL)
 			{
 			OPENSSL_free(frag);
 			return NULL;
 			}
 		}
 
 	/* zero length fragment gets zero frag->fragment */
 	frag->fragment = buf;
 
 	/* Initialize reassembly bitmask if necessary */
 	if (reassembly)
 		{
 		bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
 		if (bitmask == NULL)
 			{
 			if (buf != NULL) OPENSSL_free(buf);
 			OPENSSL_free(frag);
 			return NULL;
 			}
 		memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
 		}
 
 	frag->reassembly = bitmask;
 
 	return frag;
 	}
 
 void dtls1_hm_fragment_free(hm_fragment *frag)
 	{
 
 	if (frag->msg_header.is_ccs)
 		{
 		EVP_CIPHER_CTX_free(frag->msg_header.saved_retransmit_state.enc_write_ctx);
 		EVP_MD_CTX_destroy(frag->msg_header.saved_retransmit_state.write_hash);
 		}
 	if (frag->fragment) OPENSSL_free(frag->fragment);
 	if (frag->reassembly) OPENSSL_free(frag->reassembly);
 	OPENSSL_free(frag);
 	}
 
 static int dtls1_query_mtu(SSL *s)
 {
 	if(s->d1->link_mtu)
 		{
 		s->d1->mtu = s->d1->link_mtu-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
 		s->d1->link_mtu = 0;
 		}
 
 	/* AHA!  Figure out the MTU, and stick to the right size */
 	if (s->d1->mtu < dtls1_min_mtu(s))
 		{
 		if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
 			{
 			s->d1->mtu =
 				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
 
 			/* I've seen the kernel return bogus numbers when it doesn't know
 			 * (initial write), so just make sure we have a reasonable number */
 			if (s->d1->mtu < dtls1_min_mtu(s))
 				{
 				/* Set to min mtu */
 				s->d1->mtu = dtls1_min_mtu(s);
 				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
 					s->d1->mtu, NULL);
 				}
 			}
 		else
 			return 0;
 		}
 	return 1;
 }
 
 /* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
 int dtls1_do_write(SSL *s, int type)
 	{
 	int ret;
 	unsigned int curr_mtu;
 	int retry = 1;
 	unsigned int len, frag_off, mac_size, blocksize, used_len;
 
 	if(!dtls1_query_mtu(s))
 		return -1;
 
 	OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s));  /* should have something reasonable now */
 
 	if ( s->init_off == 0  && type == SSL3_RT_HANDSHAKE)
 		OPENSSL_assert(s->init_num == 
 			(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
 
 	if (s->write_hash)
 		mac_size = EVP_MD_CTX_size(s->write_hash);
 	else
 		mac_size = 0;
 
 	if (s->enc_write_ctx && 
 		(EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE))
 		blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
 	else
 		blocksize = 0;
 
 	frag_off = 0;
 	/* s->init_num shouldn't ever be < 0...but just in case */
 	while(s->init_num > 0)
 		{
 		used_len = BIO_wpending(SSL_get_wbio(s)) +  DTLS1_RT_HEADER_LENGTH
 			+ mac_size + blocksize;
 		if(s->d1->mtu > used_len)
 			curr_mtu = s->d1->mtu - used_len;
 		else
 			curr_mtu = 0;
 
 		if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
 			{
 			/* grr.. we could get an error if MTU picked was wrong */
 			ret = BIO_flush(SSL_get_wbio(s));
 			if ( ret <= 0)
 				return ret;
 			used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
 			if(s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH)
 				{
 				curr_mtu = s->d1->mtu - used_len;
 				}
 			else
 				{
 				/* Shouldn't happen */
 				return -1;
 				}
 			}
 
 		/* We just checked that s->init_num > 0 so this cast should be safe */
 		if (((unsigned int)s->init_num) > curr_mtu)
 			len = curr_mtu;
 		else
 			len = s->init_num;
 
 		/* Shouldn't ever happen */
 		if(len > INT_MAX)
 			len = INT_MAX;
 
 		/* XDTLS: this function is too long.  split out the CCS part */
 		if ( type == SSL3_RT_HANDSHAKE)
 			{
 			if ( s->init_off != 0)
 				{
 				OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
 				s->init_off -= DTLS1_HM_HEADER_LENGTH;
 				s->init_num += DTLS1_HM_HEADER_LENGTH;
 
 				/* We just checked that s->init_num > 0 so this cast should be safe */
 				if (((unsigned int)s->init_num) > curr_mtu)
 					len = curr_mtu;
 				else
 					len = s->init_num;
 				}
 
 			/* Shouldn't ever happen */
 			if(len > INT_MAX)
 				len = INT_MAX;
 
 			if ( len < DTLS1_HM_HEADER_LENGTH )
 				{
 				/*
 				 * len is so small that we really can't do anything sensible
 				 * so fail
 				 */
 				return -1;
 				}
 			dtls1_fix_message_header(s, frag_off, 
 				len - DTLS1_HM_HEADER_LENGTH);
 
 			dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);
 			}
 
 		ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
 			len);
 		if (ret < 0)
 			{
 			/* might need to update MTU here, but we don't know
 			 * which previous packet caused the failure -- so can't
 			 * really retransmit anything.  continue as if everything
 			 * is fine and wait for an alert to handle the
 			 * retransmit 
 			 */
 			if ( retry && BIO_ctrl(SSL_get_wbio(s),
 				BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 )
 				{
 				if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
 					{
 					if(!dtls1_query_mtu(s))
 						return -1;
 					/* Have one more go */
 					retry = 0;
 					}
 				else
 					return -1;
 				}
 			else
 				{
 				return(-1);
 				}
 			}
 		else
 			{
 
 			/* bad if this assert fails, only part of the handshake
 			 * message got sent.  but why would this happen? */
 			OPENSSL_assert(len == (unsigned int)ret);
 
 			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
 				{
 				/* should not be done for 'Hello Request's, but in that case
 				 * we'll ignore the result anyway */
 				unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
 				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
 				int xlen;
 
 				if (frag_off == 0 && s->version != DTLS1_BAD_VER)
 					{
 					/* reconstruct message header is if it
 					 * is being sent in single fragment */
 					*p++ = msg_hdr->type;
 					l2n3(msg_hdr->msg_len,p);
 					s2n (msg_hdr->seq,p);
 					l2n3(0,p);
 					l2n3(msg_hdr->msg_len,p);
 					p  -= DTLS1_HM_HEADER_LENGTH;
 					xlen = ret;
 					}
 				else
 					{
 					p  += DTLS1_HM_HEADER_LENGTH;
 					xlen = ret - DTLS1_HM_HEADER_LENGTH;
 					}
 
 				ssl3_finish_mac(s, p, xlen);
 				}
 
 			if (ret == s->init_num)
 				{
 				if (s->msg_callback)
 					s->msg_callback(1, s->version, type, s->init_buf->data, 
 						(size_t)(s->init_off + s->init_num), s, 
 						s->msg_callback_arg);
 
 				s->init_off = 0;  /* done writing this message */
 				s->init_num = 0;
 
 				return(1);
 				}
 			s->init_off+=ret;
 			s->init_num-=ret;
 			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
 			}
 		}
 	return(0);
 	}
 
 
 /* Obtain handshake message of message type 'mt' (any if mt == -1),
  * maximum acceptable body length 'max'.
  * Read an entire handshake message.  Handshake messages arrive in
  * fragments.
  */
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
 	{
 	int i, al;
 	struct hm_header_st *msg_hdr;
 	unsigned char *p;
 	unsigned long msg_len;
 
 	/* s3->tmp is used to store messages that are unexpected, caused
 	 * by the absence of an optional handshake message */
 	if (s->s3->tmp.reuse_message)
 		{
 		s->s3->tmp.reuse_message=0;
 		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
 		*ok=1;
 		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
 		s->init_num = (int)s->s3->tmp.message_size;
 		return s->init_num;
 		}
 
 	msg_hdr = &s->d1->r_msg_hdr;
 	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
 
 again:
 	i = dtls1_get_message_fragment(s, st1, stn, max, ok);
 	if ( i == DTLS1_HM_BAD_FRAGMENT ||
 		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
 		goto again;
 	else if ( i <= 0 && !*ok)
 		return i;
 
+    if (mt >= 0 && s->s3->tmp.message_type != mt) {
+        al = SSL_AD_UNEXPECTED_MESSAGE;
+        SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+        goto f_err;
+    }
+
 	p = (unsigned char *)s->init_buf->data;
 	msg_len = msg_hdr->msg_len;
 
 	/* reconstruct message header */
 	*(p++) = msg_hdr->type;
 	l2n3(msg_len,p);
 	s2n (msg_hdr->seq,p);
 	l2n3(0,p);
 	l2n3(msg_len,p);
 	if (s->version != DTLS1_BAD_VER) {
 		p       -= DTLS1_HM_HEADER_LENGTH;
 		msg_len += DTLS1_HM_HEADER_LENGTH;
 	}
 
 	ssl3_finish_mac(s, p, msg_len);
 	if (s->msg_callback)
 		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
 			p, msg_len,
 			s, s->msg_callback_arg);
 
 	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
 
 	/* Don't change sequence numbers while listening */
 	if (!s->d1->listen)
 		s->d1->handshake_read_seq++;
 
 	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
 	return s->init_num;
 
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 	*ok = 0;
 	return -1;
 	}
 
 
 static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
 	{
 	size_t frag_off,frag_len,msg_len;
 
 	msg_len  = msg_hdr->msg_len;
 	frag_off = msg_hdr->frag_off;
 	frag_len = msg_hdr->frag_len;
 
 	/* sanity checking */
 	if ( (frag_off+frag_len) > msg_len)
 		{
 		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
 		return SSL_AD_ILLEGAL_PARAMETER;
 		}
 
 	if ( (frag_off+frag_len) > (unsigned long)max)
 		{
 		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
 		return SSL_AD_ILLEGAL_PARAMETER;
 		}
 
 	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
 		{
 		/* msg_len is limited to 2^24, but is effectively checked
 		 * against max above */
 		if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH))
 			{
 			SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
 			return SSL_AD_INTERNAL_ERROR;
 			}
 
 		s->s3->tmp.message_size  = msg_len;
 		s->d1->r_msg_hdr.msg_len = msg_len;
 		s->s3->tmp.message_type  = msg_hdr->type;
 		s->d1->r_msg_hdr.type    = msg_hdr->type;
 		s->d1->r_msg_hdr.seq     = msg_hdr->seq;
 		}
 	else if (msg_len != s->d1->r_msg_hdr.msg_len)
 		{
 		/* They must be playing with us! BTW, failure to enforce
 		 * upper limit would open possibility for buffer overrun. */
 		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
 		return SSL_AD_ILLEGAL_PARAMETER;
 		}
 
 	return 0; /* no error */
 	}
 
 
 static int
 dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
 	{
 	/* (0) check whether the desired fragment is available
 	 * if so:
 	 * (1) copy over the fragment to s->init_buf->data[]
 	 * (2) update s->init_num
 	 */
 	pitem *item;
 	hm_fragment *frag;
 	int al;
 
 	*ok = 0;
 	item = pqueue_peek(s->d1->buffered_messages);
 	if ( item == NULL)
 		return 0;
 
 	frag = (hm_fragment *)item->data;
 	
 	/* Don't return if reassembly still in progress */
 	if (frag->reassembly != NULL)
 		return 0;
 
 	if ( s->d1->handshake_read_seq == frag->msg_header.seq)
 		{
 		unsigned long frag_len = frag->msg_header.frag_len;
 		pqueue_pop(s->d1->buffered_messages);
 
 		al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
 
 		if (al==0) /* no alert */
 			{
 			unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
 			memcpy(&p[frag->msg_header.frag_off],
 				frag->fragment,frag->msg_header.frag_len);
 			}
 
 		dtls1_hm_fragment_free(frag);
 		pitem_free(item);
 
 		if (al==0)
 			{
 			*ok = 1;
 			return frag_len;
 			}
 
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		s->init_num = 0;
 		*ok = 0;
 		return -1;
 		}
 	else
 		return 0;
 	}
 
 /* dtls1_max_handshake_message_len returns the maximum number of bytes
  * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
  * be greater if the maximum certificate list size requires it. */
 static unsigned long dtls1_max_handshake_message_len(const SSL *s)
 	{
 	unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
 	if (max_len < (unsigned long)s->max_cert_list)
 		return s->max_cert_list;
 	return max_len;
 	}
 
 static int
 dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
 	{
 	hm_fragment *frag = NULL;
 	pitem *item = NULL;
 	int i = -1, is_complete;
 	unsigned char seq64be[8];
 	unsigned long frag_len = msg_hdr->frag_len;
 
 	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
 	    msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
 		goto err;
 
 	if (frag_len == 0)
 		return DTLS1_HM_FRAGMENT_RETRY;
 
 	/* Try to find item in queue */
 	memset(seq64be,0,sizeof(seq64be));
 	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
 	seq64be[7] = (unsigned char) msg_hdr->seq;
 	item = pqueue_find(s->d1->buffered_messages, seq64be);
 
 	if (item == NULL)
 		{
 		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
 		if ( frag == NULL)
 			goto err;
 		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
 		frag->msg_header.frag_len = frag->msg_header.msg_len;
 		frag->msg_header.frag_off = 0;
 		}
 	else
 		{
 		frag = (hm_fragment*) item->data;
 		if (frag->msg_header.msg_len != msg_hdr->msg_len)
 			{
 			item = NULL;
 			frag = NULL;
 			goto err;
 			}
 		}
 
 
 	/* If message is already reassembled, this must be a
 	 * retransmit and can be dropped. In this case item != NULL and so frag
 	 * does not need to be freed.
 	 */
 	if (frag->reassembly == NULL)
 		{
 		unsigned char devnull [256];
 
 		while (frag_len)
 			{
 			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 				devnull,
 				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
 			if (i<=0) goto err;
 			frag_len -= i;
 			}
 		return DTLS1_HM_FRAGMENT_RETRY;
 		}
 
 	/* read the body of the fragment (header has already been read */
 	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 		frag->fragment + msg_hdr->frag_off,frag_len,0);
 	if ((unsigned long)i!=frag_len)
 		i=-1;
 	if (i<=0)
 		goto err;
 
 	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
 	                    (long)(msg_hdr->frag_off + frag_len));
 
 	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
 	                           is_complete);
 
 	if (is_complete)
 		{
 		OPENSSL_free(frag->reassembly);
 		frag->reassembly = NULL;
 		}
 
 	if (item == NULL)
 		{
 		item = pitem_new(seq64be, frag);
 		if (item == NULL)
 			{
 			i = -1;
 			goto err;
 			}
 
 		item = pqueue_insert(s->d1->buffered_messages, item);
 		/* pqueue_insert fails iff a duplicate item is inserted.
 		 * However, |item| cannot be a duplicate. If it were,
 		 * |pqueue_find|, above, would have returned it and control
 		 * would never have reached this branch. */
 		OPENSSL_assert(item != NULL);
 		}
 
 	return DTLS1_HM_FRAGMENT_RETRY;
 
 err:
 	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
 	*ok = 0;
 	return i;
 	}
 
 
 static int
 dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
 {
 	int i=-1;
 	hm_fragment *frag = NULL;
 	pitem *item = NULL;
 	unsigned char seq64be[8];
 	unsigned long frag_len = msg_hdr->frag_len;
 
 	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
 		goto err;
 
 	/* Try to find item in queue, to prevent duplicate entries */
 	memset(seq64be,0,sizeof(seq64be));
 	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
 	seq64be[7] = (unsigned char) msg_hdr->seq;
 	item = pqueue_find(s->d1->buffered_messages, seq64be);
 
 	/* If we already have an entry and this one is a fragment,
 	 * don't discard it and rather try to reassemble it.
 	 */
 	if (item != NULL && frag_len != msg_hdr->msg_len)
 		item = NULL;
 
 	/* Discard the message if sequence number was already there, is
 	 * too far in the future, already in the queue or if we received
 	 * a FINISHED before the SERVER_HELLO, which then must be a stale
 	 * retransmit.
 	 */
 	if (msg_hdr->seq <= s->d1->handshake_read_seq ||
 		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
 		(s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
 		{
 		unsigned char devnull [256];
 
 		while (frag_len)
 			{
 			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 				devnull,
 				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
 			if (i<=0) goto err;
 			frag_len -= i;
 			}
 		}
 	else
 		{
 		if (frag_len != msg_hdr->msg_len)
 			return dtls1_reassemble_fragment(s, msg_hdr, ok);
 
 		if (frag_len > dtls1_max_handshake_message_len(s))
 			goto err;
 
 		frag = dtls1_hm_fragment_new(frag_len, 0);
 		if ( frag == NULL)
 			goto err;
 
 		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
 
 		if (frag_len)
 			{
 			/* read the body of the fragment (header has already been read */
 			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 				frag->fragment,frag_len,0);
 			if ((unsigned long)i!=frag_len)
 				i = -1;
 			if (i<=0)
 				goto err;
 			}
 
 		item = pitem_new(seq64be, frag);
 		if ( item == NULL)
 			goto err;
 
 		item = pqueue_insert(s->d1->buffered_messages, item);
 		/* pqueue_insert fails iff a duplicate item is inserted.
 		 * However, |item| cannot be a duplicate. If it were,
 		 * |pqueue_find|, above, would have returned it. Then, either
 		 * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
 		 * to NULL and it will have been processed with
 		 * |dtls1_reassemble_fragment|, above, or the record will have
 		 * been discarded. */
 		OPENSSL_assert(item != NULL);
 		}
 
 	return DTLS1_HM_FRAGMENT_RETRY;
 
 err:
 	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
 	*ok = 0;
 	return i;
 	}
 
 
 static long
 dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
 	{
 	unsigned char wire[DTLS1_HM_HEADER_LENGTH];
 	unsigned long len, frag_off, frag_len;
 	int i,al;
 	struct hm_header_st msg_hdr;
 
 	redo:
 	/* see if we have the required fragment already */
 	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
 		{
 		if (*ok)	s->init_num = frag_len;
 		return frag_len;
 		}
 
 	/* read handshake message header */
 	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
 		DTLS1_HM_HEADER_LENGTH, 0);
 	if (i <= 0) 	/* nbio, or an error */
 		{
 		s->rwstate=SSL_READING;
 		*ok = 0;
 		return i;
 		}
 	/* Handshake fails if message header is incomplete */
 	if (i != DTLS1_HM_HEADER_LENGTH)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
 		goto f_err;
 		}
 
 	/* parse the message fragment header */
 	dtls1_get_message_header(wire, &msg_hdr);
 
+    len = msg_hdr.msg_len;
+    frag_off = msg_hdr.frag_off;
+    frag_len = msg_hdr.frag_len;
+
+    /*
+     * We must have at least frag_len bytes left in the record to be read.
+     * Fragments must not span records.
+     */
+    if (frag_len > s->s3->rrec.length) {
+        al = SSL3_AD_ILLEGAL_PARAMETER;
+        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_LENGTH);
+        goto f_err;
+    }
+
 	/* 
 	 * if this is a future (or stale) message it gets buffered
 	 * (or dropped)--no further processing at this time
 	 * While listening, we accept seq 1 (ClientHello with cookie)
 	 * although we're still expecting seq 0 (ClientHello)
 	 */
 	if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1))
 		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
 
-	len = msg_hdr.msg_len;
-	frag_off = msg_hdr.frag_off;
-	frag_len = msg_hdr.frag_len;
-
 	if (frag_len && frag_len < len)
 		return dtls1_reassemble_fragment(s, &msg_hdr, ok);
 
 	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
 		wire[0] == SSL3_MT_HELLO_REQUEST)
 		{
 		/* The server may always send 'Hello Request' messages --
 		 * we are doing a handshake anyway now, so ignore them
 		 * if their format is correct. Does not count for
 		 * 'Finished' MAC. */
 		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
 			{
 			if (s->msg_callback)
 				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
 					wire, DTLS1_HM_HEADER_LENGTH, s, 
 					s->msg_callback_arg);
 			
 			s->init_num = 0;
 			goto redo;
 			}
 		else /* Incorrectly formated Hello request */
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
 		}
 
 	if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
 		goto f_err;
 
-	/* XDTLS:  ressurect this when restart is in place */
-	s->state=stn;
-
 	if ( frag_len > 0)
 		{
 		unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
 
 		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 			&p[frag_off],frag_len,0);
-		/* XDTLS:  fix this--message fragments cannot span multiple packets */
+		/*
+		 * This shouldn't ever fail due to NBIO because we already checked
+		 * that we have enough data in the record
+		 */
 		if (i <= 0)
 			{
 			s->rwstate=SSL_READING;
 			*ok = 0;
 			return i;
 			}
 		}
 	else
 		i = 0;
 
 	/* XDTLS:  an incorrectly formatted fragment should cause the 
 	 * handshake to fail */
 	if (i != (int)frag_len)
 		{
 		al=SSL3_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER);
 		goto f_err;
 		}
 
 	*ok = 1;
+    s->state = stn;
 
 	/* Note that s->init_num is *not* used as current offset in
 	 * s->init_buf->data, but as a counter summing up fragments'
 	 * lengths: as soon as they sum up to handshake packet
 	 * length, we assume we have got all the fragments. */
 	s->init_num = frag_len;
 	return frag_len;
 
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 	s->init_num = 0;
 
 	*ok=0;
 	return(-1);
 	}
 
 int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen)
 	{
 	unsigned char *p,*d;
 	int i;
 	unsigned long l;
 
 	if (s->state == a)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[DTLS1_HM_HEADER_LENGTH]);
 
 		i=s->method->ssl3_enc->final_finish_mac(s,
 			sender,slen,s->s3->tmp.finish_md);
 		s->s3->tmp.finish_md_len = i;
 		memcpy(p, s->s3->tmp.finish_md, i);
 		p+=i;
 		l=i;
 
 	/* Copy the finished so we can use it for
 	 * renegotiation checks
 	 */
 	if(s->type == SSL_ST_CONNECT)
 		{
 		OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
 		memcpy(s->s3->previous_client_finished, 
 		       s->s3->tmp.finish_md, i);
 		s->s3->previous_client_finished_len=i;
 		}
 	else
 		{
 		OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
 		memcpy(s->s3->previous_server_finished, 
 		       s->s3->tmp.finish_md, i);
 		s->s3->previous_server_finished_len=i;
 		}
 
 #ifdef OPENSSL_SYS_WIN16
 		/* MSVC 1.5 does not clear the top bytes of the word unless
 		 * I do this.
 		 */
 		l&=0xffff;
 #endif
 
 		d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l);
 		s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH;
 		s->init_off=0;
 
 		/* buffer the message to handle re-xmits */
 		dtls1_buffer_message(s, 0);
 
 		s->state=b;
 		}
 
 	/* SSL3_ST_SEND_xxxxxx_HELLO_B */
 	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 /* for these 2 messages, we need to
  * ssl->enc_read_ctx			re-init
  * ssl->s3->read_sequence		zero
  * ssl->s3->read_mac_secret		re-init
  * ssl->session->read_sym_enc		assign
  * ssl->session->read_compression	assign
  * ssl->session->read_hash		assign
  */
 int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
 	{ 
 	unsigned char *p;
 
 	if (s->state == a)
 		{
 		p=(unsigned char *)s->init_buf->data;
 		*p++=SSL3_MT_CCS;
 		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
 		s->init_num=DTLS1_CCS_HEADER_LENGTH;
 
 		if (s->version == DTLS1_BAD_VER) {
 			s->d1->next_handshake_write_seq++;
 			s2n(s->d1->handshake_write_seq,p);
 			s->init_num+=2;
 		}
 
 		s->init_off=0;
 
 		dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, 
 			s->d1->handshake_write_seq, 0, 0);
 
 		/* buffer the message to handle re-xmits */
 		dtls1_buffer_message(s, 1);
 
 		s->state=b;
 		}
 
 	/* SSL3_ST_CW_CHANGE_B */
 	return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
 	}
 
 static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
 	{
 	int n;
 	unsigned char *p;
 
 	n=i2d_X509(x,NULL);
 	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
 		{
 		SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
 		return 0;
 		}
 	p=(unsigned char *)&(buf->data[*l]);
 	l2n3(n,p);
 	i2d_X509(x,&p);
 	*l+=n+3;
 
 	return 1;
 	}
 unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
 	{
 	unsigned char *p;
 	int i;
 	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
 	BUF_MEM *buf;
 
 	/* TLSv1 sends a chain with nothing in it, instead of an alert */
 	buf=s->init_buf;
 	if (!BUF_MEM_grow_clean(buf,10))
 		{
 		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
 		return(0);
 		}
 	if (x != NULL)
 		{
 		X509_STORE_CTX xs_ctx;
 
 		if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
   			{
   			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
   			return(0);
   			}
   
 		X509_verify_cert(&xs_ctx);
 		/* Don't leave errors in the queue */
 		ERR_clear_error();
 		for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
   			{
 			x = sk_X509_value(xs_ctx.chain, i);
 
 			if (!dtls1_add_cert_to_buf(buf, &l, x))
   				{
 				X509_STORE_CTX_cleanup(&xs_ctx);
 				return 0;
   				}
   			}
   		X509_STORE_CTX_cleanup(&xs_ctx);
   		}
   	/* Thawte special :-) */
 	for (i=0; ictx->extra_certs); i++)
 		{
 		x=sk_X509_value(s->ctx->extra_certs,i);
 		if (!dtls1_add_cert_to_buf(buf, &l, x))
 			return 0;
 		}
 
 	l-= (3 + DTLS1_HM_HEADER_LENGTH);
 
 	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
 	l2n3(l,p);
 	l+=3;
 	p=(unsigned char *)&(buf->data[0]);
 	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);
 
 	l+=DTLS1_HM_HEADER_LENGTH;
 	return(l);
 	}
 
 int dtls1_read_failed(SSL *s, int code)
 	{
 	if ( code > 0)
 		{
 		fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
 		return 1;
 		}
 
 	if (!dtls1_is_timer_expired(s))
 		{
 		/* not a timeout, none of our business, 
 		   let higher layers handle this.  in fact it's probably an error */
 		return code;
 		}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	if (!SSL_in_init(s) && !s->tlsext_hb_pending)  /* done, no need to send a retransmit */
 #else
 	if (!SSL_in_init(s))  /* done, no need to send a retransmit */
 #endif
 		{
 		BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
 		return code;
 		}
 
 #if 0 /* for now, each alert contains only one record number */
 	item = pqueue_peek(state->rcvd_records);
 	if ( item )
 		{
 		/* send an alert immediately for all the missing records */
 		}
 	else
 #endif
 
 #if 0  /* no more alert sending, just retransmit the last set of messages */
 	if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
 		ssl3_send_alert(s,SSL3_AL_WARNING,
 			DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
 #endif
 
 	return dtls1_handle_timeout(s);
 	}
 
 int
 dtls1_get_queue_priority(unsigned short seq, int is_ccs)
 	{
 	/* The index of the retransmission queue actually is the message sequence number,
 	 * since the queue only contains messages of a single handshake. However, the
 	 * ChangeCipherSpec has no message sequence number and so using only the sequence
 	 * will result in the CCS and Finished having the same index. To prevent this,
 	 * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted.
 	 * This does not only differ CSS and Finished, it also maintains the order of the
 	 * index (important for priority queues) and fits in the unsigned short variable.
 	 */	
 	return seq * 2 - is_ccs;
 	}
 
 int
 dtls1_retransmit_buffered_messages(SSL *s)
 	{
 	pqueue sent = s->d1->sent_messages;
 	piterator iter;
 	pitem *item;
 	hm_fragment *frag;
 	int found = 0;
 
 	iter = pqueue_iterator(sent);
 
 	for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
 		{
 		frag = (hm_fragment *)item->data;
 			if ( dtls1_retransmit_message(s,
 				(unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs),
 				0, &found) <= 0 && found)
 			{
 			fprintf(stderr, "dtls1_retransmit_message() failed\n");
 			return -1;
 			}
 		}
 
 	return 1;
 	}
 
 int
 dtls1_buffer_message(SSL *s, int is_ccs)
 	{
 	pitem *item;
 	hm_fragment *frag;
 	unsigned char seq64be[8];
 
 	/* this function is called immediately after a message has 
 	 * been serialized */
 	OPENSSL_assert(s->init_off == 0);
 
 	frag = dtls1_hm_fragment_new(s->init_num, 0);
 	if (!frag)
 		return 0;
 
 	memcpy(frag->fragment, s->init_buf->data, s->init_num);
 
 	if ( is_ccs)
 		{
 		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
 			       ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num);
 		}
 	else
 		{
 		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
 			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
 		}
 
 	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
 	frag->msg_header.seq = s->d1->w_msg_hdr.seq;
 	frag->msg_header.type = s->d1->w_msg_hdr.type;
 	frag->msg_header.frag_off = 0;
 	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
 	frag->msg_header.is_ccs = is_ccs;
 
 	/* save current state*/
 	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
 	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
 	frag->msg_header.saved_retransmit_state.compress = s->compress;
 	frag->msg_header.saved_retransmit_state.session = s->session;
 	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
 	
 	memset(seq64be,0,sizeof(seq64be));
 	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
 														  frag->msg_header.is_ccs)>>8);
 	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
 														  frag->msg_header.is_ccs));
 
 	item = pitem_new(seq64be, frag);
 	if ( item == NULL)
 		{
 		dtls1_hm_fragment_free(frag);
 		return 0;
 		}
 
 #if 0
 	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
 	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
 	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
 #endif
 
 	pqueue_insert(s->d1->sent_messages, item);
 	return 1;
 	}
 
 int
 dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
 	int *found)
 	{
 	int ret;
 	/* XDTLS: for now assuming that read/writes are blocking */
 	pitem *item;
 	hm_fragment *frag ;
 	unsigned long header_length;
 	unsigned char seq64be[8];
 	struct dtls1_retransmit_state saved_state;
 	unsigned char save_write_sequence[8];
 
 	/*
 	  OPENSSL_assert(s->init_num == 0);
 	  OPENSSL_assert(s->init_off == 0);
 	 */
 
 	/* XDTLS:  the requested message ought to be found, otherwise error */
 	memset(seq64be,0,sizeof(seq64be));
 	seq64be[6] = (unsigned char)(seq>>8);
 	seq64be[7] = (unsigned char)seq;
 
 	item = pqueue_find(s->d1->sent_messages, seq64be);
 	if ( item == NULL)
 		{
 		fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
 		*found = 0;
 		return 0;
 		}
 
 	*found = 1;
 	frag = (hm_fragment *)item->data;
 
 	if ( frag->msg_header.is_ccs)
 		header_length = DTLS1_CCS_HEADER_LENGTH;
 	else
 		header_length = DTLS1_HM_HEADER_LENGTH;
 
 	memcpy(s->init_buf->data, frag->fragment, 
 		frag->msg_header.msg_len + header_length);
 		s->init_num = frag->msg_header.msg_len + header_length;
 
 	dtls1_set_message_header_int(s, frag->msg_header.type, 
 		frag->msg_header.msg_len, frag->msg_header.seq, 0, 
 		frag->msg_header.frag_len);
 
 	/* save current state */
 	saved_state.enc_write_ctx = s->enc_write_ctx;
 	saved_state.write_hash = s->write_hash;
 	saved_state.compress = s->compress;
 	saved_state.session = s->session;
 	saved_state.epoch = s->d1->w_epoch;
 	saved_state.epoch = s->d1->w_epoch;
 	
 	s->d1->retransmitting = 1;
 	
 	/* restore state in which the message was originally sent */
 	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
 	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
 	s->compress = frag->msg_header.saved_retransmit_state.compress;
 	s->session = frag->msg_header.saved_retransmit_state.session;
 	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
 	
 	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
 	{
 		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
 		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
 	}
 	
 	ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
 						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
 	
 	/* restore current state */
 	s->enc_write_ctx = saved_state.enc_write_ctx;
 	s->write_hash = saved_state.write_hash;
 	s->compress = saved_state.compress;
 	s->session = saved_state.session;
 	s->d1->w_epoch = saved_state.epoch;
 	
 	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
 	{
 		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
 		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
 	}
 
 	s->d1->retransmitting = 0;
 
 	(void)BIO_flush(SSL_get_wbio(s));
 	return ret;
 	}
 
 /* call this function when the buffered messages are no longer needed */
 void
 dtls1_clear_record_buffer(SSL *s)
 	{
 	pitem *item;
 
 	for(item = pqueue_pop(s->d1->sent_messages);
 		item != NULL; item = pqueue_pop(s->d1->sent_messages))
 		{
 		dtls1_hm_fragment_free((hm_fragment *)item->data);
 		pitem_free(item);
 		}
 	}
 
 
 unsigned char *
 dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
 			unsigned long len, unsigned long frag_off, unsigned long frag_len)
 	{
 	/* Don't change sequence numbers while listening */
 	if (frag_off == 0 && !s->d1->listen)
 		{
 		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
 		s->d1->next_handshake_write_seq++;
 		}
 
 	dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
 		frag_off, frag_len);
 
 	return p += DTLS1_HM_HEADER_LENGTH;
 	}
 
 
 /* don't actually do the writing, wait till the MTU has been retrieved */
 static void
 dtls1_set_message_header_int(SSL *s, unsigned char mt,
 			    unsigned long len, unsigned short seq_num, unsigned long frag_off,
 			    unsigned long frag_len)
 	{
 	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
 
 	msg_hdr->type = mt;
 	msg_hdr->msg_len = len;
 	msg_hdr->seq = seq_num;
 	msg_hdr->frag_off = frag_off;
 	msg_hdr->frag_len = frag_len;
 	}
 
 static void
 dtls1_fix_message_header(SSL *s, unsigned long frag_off,
 			unsigned long frag_len)
 	{
 	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
 
 	msg_hdr->frag_off = frag_off;
 	msg_hdr->frag_len = frag_len;
 	}
 
 static unsigned char *
 dtls1_write_message_header(SSL *s, unsigned char *p)
 	{
 	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
 
 	*p++ = msg_hdr->type;
 	l2n3(msg_hdr->msg_len, p);
 
 	s2n(msg_hdr->seq, p);
 	l2n3(msg_hdr->frag_off, p);
 	l2n3(msg_hdr->frag_len, p);
 
 	return p;
 	}
 
 unsigned int
 dtls1_link_min_mtu(void)
 	{
 	return (g_probable_mtu[(sizeof(g_probable_mtu) / 
 		sizeof(g_probable_mtu[0])) - 1]);
 	}
 
 unsigned int
 dtls1_min_mtu(SSL *s)
 	{
 	return dtls1_link_min_mtu()-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
 	}
 
 
 void
 dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
 	{
 	memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
 	msg_hdr->type = *(data++);
 	n2l3(data, msg_hdr->msg_len);
 
 	n2s(data, msg_hdr->seq);
 	n2l3(data, msg_hdr->frag_off);
 	n2l3(data, msg_hdr->frag_len);
 	}
 
 void
 dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
 	{
 	memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
 
 	ccs_hdr->type = *(data++);
 	}
 
 int dtls1_shutdown(SSL *s)
 	{
 	int ret;
 #ifndef OPENSSL_NO_SCTP
 	if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
 	    !(s->shutdown & SSL_SENT_SHUTDOWN))
 		{
 		ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
 		if (ret < 0) return -1;
 
 		if (ret == 0)
 			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, NULL);
 		}
 #endif
 	ret = ssl3_shutdown(s);
 #ifndef OPENSSL_NO_SCTP
 	BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
 #endif
 	return ret;
 	}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 int
 dtls1_process_heartbeat(SSL *s)
 	{
 	unsigned char *p = &s->s3->rrec.data[0], *pl;
 	unsigned short hbtype;
 	unsigned int payload;
 	unsigned int padding = 16; /* Use minimum padding */
 
 	if (s->msg_callback)
 		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
 			&s->s3->rrec.data[0], s->s3->rrec.length,
 			s, s->msg_callback_arg);
 
 	/* Read type and payload length first */
 	if (1 + 2 + 16 > s->s3->rrec.length)
 		return 0; /* silently discard */
 	if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)
 		return 0; /* silently discard per RFC 6520 sec. 4 */
 
 	hbtype = *p++;
 	n2s(p, payload);
 	if (1 + 2 + payload + 16 > s->s3->rrec.length)
 		return 0; /* silently discard per RFC 6520 sec. 4 */
 	pl = p;
 
 	if (hbtype == TLS1_HB_REQUEST)
 		{
 		unsigned char *buffer, *bp;
 		unsigned int write_length = 1 /* heartbeat type */ +
 					    2 /* heartbeat length */ +
 					    payload + padding;
 		int r;
 
 		if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
 			return 0;
 
 		/* Allocate memory for the response, size is 1 byte
 		 * message type, plus 2 bytes payload length, plus
 		 * payload, plus padding
 		 */
 		buffer = OPENSSL_malloc(write_length);
 		bp = buffer;
 
 		/* Enter response type, length and copy payload */
 		*bp++ = TLS1_HB_RESPONSE;
 		s2n(payload, bp);
 		memcpy(bp, pl, payload);
 		bp += payload;
 		/* Random padding */
 		RAND_pseudo_bytes(bp, padding);
 
 		r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
 
 		if (r >= 0 && s->msg_callback)
 			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
 				buffer, write_length,
 				s, s->msg_callback_arg);
 
 		OPENSSL_free(buffer);
 
 		if (r < 0)
 			return r;
 		}
 	else if (hbtype == TLS1_HB_RESPONSE)
 		{
 		unsigned int seq;
 
 		/* We only send sequence numbers (2 bytes unsigned int),
 		 * and 16 random bytes, so we just try to read the
 		 * sequence number */
 		n2s(pl, seq);
 
 		if (payload == 18 && seq == s->tlsext_hb_seq)
 			{
 			dtls1_stop_timer(s);
 			s->tlsext_hb_seq++;
 			s->tlsext_hb_pending = 0;
 			}
 		}
 
 	return 0;
 	}
 
 int
 dtls1_heartbeat(SSL *s)
 	{
 	unsigned char *buf, *p;
 	int ret;
 	unsigned int payload = 18; /* Sequence number + random bytes */
 	unsigned int padding = 16; /* Use minimum padding */
 
 	/* Only send if peer supports and accepts HB requests... */
 	if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
 	    s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS)
 		{
 		SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
 		return -1;
 		}
 
 	/* ...and there is none in flight yet... */
 	if (s->tlsext_hb_pending)
 		{
 		SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PENDING);
 		return -1;
 		}
 
 	/* ...and no handshake in progress. */
 	if (SSL_in_init(s) || s->in_handshake)
 		{
 		SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_UNEXPECTED_MESSAGE);
 		return -1;
 		}
 
 	/* Check if padding is too long, payload and padding
 	 * must not exceed 2^14 - 3 = 16381 bytes in total.
 	 */
 	OPENSSL_assert(payload + padding <= 16381);
 
 	/* Create HeartBeat message, we just use a sequence number
 	 * as payload to distuingish different messages and add
 	 * some random stuff.
 	 *  - Message Type, 1 byte
 	 *  - Payload Length, 2 bytes (unsigned int)
 	 *  - Payload, the sequence number (2 bytes uint)
 	 *  - Payload, random bytes (16 bytes uint)
 	 *  - Padding
 	 */
 	buf = OPENSSL_malloc(1 + 2 + payload + padding);
 	p = buf;
 	/* Message Type */
 	*p++ = TLS1_HB_REQUEST;
 	/* Payload length (18 bytes here) */
 	s2n(payload, p);
 	/* Sequence number */
 	s2n(s->tlsext_hb_seq, p);
 	/* 16 random bytes */
 	RAND_pseudo_bytes(p, 16);
 	p += 16;
 	/* Random padding */
 	RAND_pseudo_bytes(p, padding);
 
 	ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
 	if (ret >= 0)
 		{
 		if (s->msg_callback)
 			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
 				buf, 3 + payload + padding,
 				s, s->msg_callback_arg);
 
 		dtls1_start_timer(s);
 		s->tlsext_hb_pending = 1;
 		}
 
 	OPENSSL_free(buf);
 
 	return ret;
 	}
 #endif
Index: releng/10.1/crypto/openssl/ssl/d1_lib.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/d1_lib.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/d1_lib.c	(revision 284295)
@@ -1,520 +1,523 @@
 /* ssl/d1_lib.c */
 /* 
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  */
 /* ====================================================================
  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 #define USE_SOCKETS
 #include 
 #include "ssl_locl.h"
 
 #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
 #include 
 #endif
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
 int dtls1_listen(SSL *s, struct sockaddr *client);
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
 	tls1_mac,
 	tls1_setup_key_block,
 	tls1_generate_master_secret,
 	tls1_change_cipher_state,
 	tls1_final_finish_mac,
 	TLS1_FINISH_MAC_LENGTH,
 	tls1_cert_verify_mac,
 	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
 	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
 	tls1_alert_code,
 	tls1_export_keying_material,
 	};
 
 long dtls1_default_timeout(void)
 	{
 	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec
 	 * is way too long for http, the cache would over fill */
 	return(60*60*2);
 	}
 
 int dtls1_new(SSL *s)
 	{
 	DTLS1_STATE *d1;
 
 	if (!ssl3_new(s)) return(0);
 	if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0);
 	memset(d1,0, sizeof *d1);
 
 	/* d1->handshake_epoch=0; */
 
 	d1->unprocessed_rcds.q=pqueue_new();
 	d1->processed_rcds.q=pqueue_new();
 	d1->buffered_messages = pqueue_new();
 	d1->sent_messages=pqueue_new();
 	d1->buffered_app_data.q=pqueue_new();
 
 	if ( s->server)
 		{
 		d1->cookie_len = sizeof(s->d1->cookie);
 		}
 
 	d1->link_mtu = 0;
 	d1->mtu = 0;
 
 	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
         || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
 		{
         if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
         if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
         if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
 		if ( d1->sent_messages) pqueue_free(d1->sent_messages);
 		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
 		OPENSSL_free(d1);
 		return (0);
 		}
 
 	s->d1=d1;
 	s->method->ssl_clear(s);
 	return(1);
 	}
 
 static void dtls1_clear_queues(SSL *s)
 	{
     pitem *item = NULL;
     hm_fragment *frag = NULL;
 	DTLS1_RECORD_DATA *rdata;
 
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         dtls1_hm_fragment_free(frag);
         pitem_free(item);
         }
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         dtls1_hm_fragment_free(frag);
         pitem_free(item);
         }
 
 	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
 		{
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
 		OPENSSL_free(item->data);
 		pitem_free(item);
 		}
 	}
 
 void dtls1_free(SSL *s)
 	{
 	ssl3_free(s);
 
 	dtls1_clear_queues(s);
 
     pqueue_free(s->d1->unprocessed_rcds.q);
     pqueue_free(s->d1->processed_rcds.q);
     pqueue_free(s->d1->buffered_messages);
 	pqueue_free(s->d1->sent_messages);
 	pqueue_free(s->d1->buffered_app_data.q);
 
 	OPENSSL_free(s->d1);
 	s->d1 = NULL;
 	}
 
 void dtls1_clear(SSL *s)
 	{
     pqueue unprocessed_rcds;
     pqueue processed_rcds;
     pqueue buffered_messages;
 	pqueue sent_messages;
 	pqueue buffered_app_data;
 	unsigned int mtu;
 	unsigned int link_mtu;
 
 	if (s->d1)
 		{
 		unprocessed_rcds = s->d1->unprocessed_rcds.q;
 		processed_rcds = s->d1->processed_rcds.q;
 		buffered_messages = s->d1->buffered_messages;
 		sent_messages = s->d1->sent_messages;
 		buffered_app_data = s->d1->buffered_app_data.q;
 		mtu = s->d1->mtu;
 		link_mtu = s->d1->link_mtu;
 
 		dtls1_clear_queues(s);
 
 		memset(s->d1, 0, sizeof(*(s->d1)));
 
 		if (s->server)
 			{
 			s->d1->cookie_len = sizeof(s->d1->cookie);
 			}
 
 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
 			{
 			s->d1->mtu = mtu;
 			s->d1->link_mtu = link_mtu;
 			}
 
 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
 		s->d1->processed_rcds.q = processed_rcds;
 		s->d1->buffered_messages = buffered_messages;
 		s->d1->sent_messages = sent_messages;
 		s->d1->buffered_app_data.q = buffered_app_data;
 		}
 
 	ssl3_clear(s);
 	if (s->options & SSL_OP_CISCO_ANYCONNECT)
 		s->version=DTLS1_BAD_VER;
 	else
 		s->version=DTLS1_VERSION;
 	}
 
 long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
 	{
 	int ret=0;
 
 	switch (cmd)
 		{
 	case DTLS_CTRL_GET_TIMEOUT:
 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
 			{
 			ret = 1;
 			}
 		break;
 	case DTLS_CTRL_HANDLE_TIMEOUT:
 		ret = dtls1_handle_timeout(s);
 		break;
 	case DTLS_CTRL_LISTEN:
 		ret = dtls1_listen(s, parg);
 		break;
 	case SSL_CTRL_CHECK_PROTO_VERSION:
 		/* For library-internal use; checks that the current protocol
 		 * is the highest enabled version (according to s->ctx->method,
 		 * as version negotiation may have changed s->method). */
 #if DTLS_MAX_VERSION != DTLS1_VERSION
 #  error Code needs update for DTLS_method() support beyond DTLS1_VERSION.
 #endif
 		/* Just one protocol version is supported so far;
 		 * fail closed if the version is not as expected. */
 		return s->version == DTLS_MAX_VERSION;
 	case DTLS_CTRL_SET_LINK_MTU:
 		if (larg < (long)dtls1_link_min_mtu())
 			return 0;
 		s->d1->link_mtu = larg;
 		return 1;
 	case DTLS_CTRL_GET_LINK_MIN_MTU:
 		return (long)dtls1_link_min_mtu();
 	case SSL_CTRL_SET_MTU:
 		/*
 		 *  We may not have a BIO set yet so can't call dtls1_min_mtu()
 		 *  We'll have to make do with dtls1_link_min_mtu() and max overhead
 		 */
 		if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
 			return 0;
 		s->d1->mtu = larg;
 		return larg;
 	default:
 		ret = ssl3_ctrl(s, cmd, larg, parg);
 		break;
 		}
 	return(ret);
 	}
 
 /*
  * As it's impossible to use stream ciphers in "datagram" mode, this
  * simple filter is designed to disengage them in DTLS. Unfortunately
  * there is no universal way to identify stream SSL_CIPHER, so we have
  * to explicitly list their SSL_* codes. Currently RC4 is the only one
  * available, but if new ones emerge, they will have to be added...
  */
 const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
 	{
 	const SSL_CIPHER *ciph = ssl3_get_cipher(u);
 
 	if (ciph != NULL)
 		{
 		if (ciph->algorithm_enc == SSL_RC4)
 			return NULL;
 		}
 
 	return ciph;
 	}
 
 void dtls1_start_timer(SSL *s)
 	{
 #ifndef OPENSSL_NO_SCTP
 	/* Disable timer for SCTP */
 	if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
 		{
 		memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
 		return;
 		}
 #endif
 
 	/* If timer is not set, initialize duration with 1 second */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		s->d1->timeout_duration = 1;
 		}
 	
 	/* Set timeout to current time */
 	get_current_time(&(s->d1->next_timeout));
 
 	/* Add duration to current time */
 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	}
 
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
 	{
 	struct timeval timenow;
 
 	/* If no timeout is set, just return NULL */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		return NULL;
 		}
 
 	/* Get current time */
 	get_current_time(&timenow);
 
 	/* If timer already expired, set remaining time to 0 */
 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
 		(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
 		 s->d1->next_timeout.tv_usec <= timenow.tv_usec))
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		return timeleft;
 		}
 
 	/* Calculate time left until timer expires */
 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
 	timeleft->tv_sec -= timenow.tv_sec;
 	timeleft->tv_usec -= timenow.tv_usec;
 	if (timeleft->tv_usec < 0)
 		{
 		timeleft->tv_sec--;
 		timeleft->tv_usec += 1000000;
 		}
 
 	/* If remaining time is less than 15 ms, set it to 0
 	 * to prevent issues because of small devergences with
 	 * socket timeouts.
 	 */
 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		}
 	
 
 	return timeleft;
 	}
 
 int dtls1_is_timer_expired(SSL *s)
 	{
 	struct timeval timeleft;
 
 	/* Get time left until timeout, return false if no timer running */
 	if (dtls1_get_timeout(s, &timeleft) == NULL)
 		{
 		return 0;
 		}
 
 	/* Return false if timer is not expired yet */
 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
 		{
 		return 0;
 		}
 
 	/* Timer expired, so return true */	
 	return 1;
 	}
 
 void dtls1_double_timeout(SSL *s)
 	{
 	s->d1->timeout_duration *= 2;
 	if (s->d1->timeout_duration > 60)
 		s->d1->timeout_duration = 60;
 	dtls1_start_timer(s);
 	}
 
 void dtls1_stop_timer(SSL *s)
 	{
 	/* Reset everything */
 	memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
 	s->d1->timeout_duration = 1;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	/* Clear retransmission buffer */
 	dtls1_clear_record_buffer(s);
 	}
 
 int dtls1_check_timeout_num(SSL *s)
 	{
 	unsigned int mtu;
 
 	s->d1->timeout.num_alerts++;
 
 	/* Reduce MTU after 2 unsuccessful retransmissions */
 	if (s->d1->timeout.num_alerts > 2
 			&& !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
 		{
 		mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
 		if(mtu < s->d1->mtu)
 			s->d1->mtu = mtu;
 		}
 
 	if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
 		{
 		/* fail the connection, enough alerts have been sent */
 		SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM,SSL_R_READ_TIMEOUT_EXPIRED);
 		return -1;
 		}
 
 	return 0;
 	}
 
 int dtls1_handle_timeout(SSL *s)
 	{
 	/* if no timer is expired, don't do anything */
 	if (!dtls1_is_timer_expired(s))
 		{
 		return 0;
 		}
 
 	dtls1_double_timeout(s);
 
 	if (dtls1_check_timeout_num(s) < 0)
 		return -1;
 
 	s->d1->timeout.read_timeouts++;
 	if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
 		{
 		s->d1->timeout.read_timeouts = 1;
 		}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	if (s->tlsext_hb_pending)
 		{
 		s->tlsext_hb_pending = 0;
 		return dtls1_heartbeat(s);
 		}
 #endif
 
 	dtls1_start_timer(s);
 	return dtls1_retransmit_buffered_messages(s);
 	}
 
 static void get_current_time(struct timeval *t)
 {
 #ifdef OPENSSL_SYS_WIN32
 	struct _timeb tb;
 	_ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #elif defined(OPENSSL_SYS_VMS)
 	struct timeb tb;
 	ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #else
 	gettimeofday(t, NULL);
 #endif
 }
 
 int dtls1_listen(SSL *s, struct sockaddr *client)
 	{
 	int ret;
 
+    /* Ensure there is no state left over from a previous invocation */
+    SSL_clear(s);
+
 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
 	s->d1->listen = 1;
 
 	ret = SSL_accept(s);
 	if (ret <= 0) return ret;
 	
 	(void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
 	return 1;
 	}
Index: releng/10.1/crypto/openssl/ssl/d1_pkt.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/d1_pkt.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/d1_pkt.c	(revision 284295)
@@ -1,1912 +1,1912 @@
 /* ssl/d1_pkt.c */
 /* 
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #define USE_SOCKETS
 #include "ssl_locl.h"
 #include 
 #include 
 #include 
 #include 
 
 /* mod 128 saturating subtract of two 64-bit values in big-endian order */
 static int satsub64be(const unsigned char *v1,const unsigned char *v2)
 {	int ret,sat,brw,i;
 
 	if (sizeof(long) == 8) do
 	{	const union { long one; char little; } is_endian = {1};
 		long l;
 
 		if (is_endian.little)			break;
 		/* not reached on little-endians */
 		/* following test is redundant, because input is
 		 * always aligned, but I take no chances... */
 		if (((size_t)v1|(size_t)v2)&0x7)	break;
 
 		l  = *((long *)v1);
 		l -= *((long *)v2);
 		if (l>128)		return 128;
 		else if (l<-128)	return -128;
 		else			return (int)l;
 	} while (0);
 
 	ret = (int)v1[7]-(int)v2[7];
 	sat = 0;
 	brw = ret>>8;	/* brw is either 0 or -1 */
 	if (ret & 0x80)
 	{	for (i=6;i>=0;i--)
 		{	brw += (int)v1[i]-(int)v2[i];
 			sat |= ~brw;
 			brw >>= 8;
 		}
 	}
 	else
 	{	for (i=6;i>=0;i--)
 		{	brw += (int)v1[i]-(int)v2[i];
 			sat |= brw;
 			brw >>= 8;
 		}
 	}
 	brw <<= 8;	/* brw is either 0 or -256 */
 
 	if (sat&0xff)	return brw | 0x80;
 	else		return brw + (ret&0xFF);
 }
 
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
 	int len, int peek);
 static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
 static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
 static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, 
     unsigned int *is_next_epoch);
 #if 0
 static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
 	unsigned short *priority, unsigned long *offset);
 #endif
 static int dtls1_buffer_record(SSL *s, record_pqueue *q,
 	unsigned char *priority);
 static int dtls1_process_record(SSL *s);
 
 /* copy buffered record into SSL structure */
 static int
 dtls1_copy_record(SSL *s, pitem *item)
     {
     DTLS1_RECORD_DATA *rdata;
 
     rdata = (DTLS1_RECORD_DATA *)item->data;
     
     if (s->s3->rbuf.buf != NULL)
         OPENSSL_free(s->s3->rbuf.buf);
     
     s->packet = rdata->packet;
     s->packet_length = rdata->packet_length;
     memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
     memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
 	
 	/* Set proper sequence number for mac calculation */
 	memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
     
     return(1);
     }
 
 
 static int
 dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
 	{
 	DTLS1_RECORD_DATA *rdata;
 	pitem *item;
 
 	/* Limit the size of the queue to prevent DOS attacks */
 	if (pqueue_size(queue->q) >= 100)
 		return 0;
 
 	rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
 	item = pitem_new(priority, rdata);
 	if (rdata == NULL || item == NULL)
 		{
 		if (rdata != NULL) OPENSSL_free(rdata);
 		if (item != NULL) pitem_free(item);
 		
 		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
 		return(0);
 		}
 	
 	rdata->packet = s->packet;
 	rdata->packet_length = s->packet_length;
 	memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
 	memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
 
 	item->data = rdata;
 
 #ifndef OPENSSL_NO_SCTP
 	/* Store bio_dgram_sctp_rcvinfo struct */
 	if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
 	    (s->state == SSL3_ST_SR_FINISHED_A || s->state == SSL3_ST_CR_FINISHED_A)) {
 		BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
 	}
 #endif
 
 	s->packet = NULL;
 	s->packet_length = 0;
 	memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
 	memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
 	
 	if (!ssl3_setup_buffers(s))
 		{
 		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
 		if (rdata->rbuf.buf != NULL)
 			OPENSSL_free(rdata->rbuf.buf);
 		OPENSSL_free(rdata);
 		pitem_free(item);
 		return(-1);
 		}
 
 	/* insert should not fail, since duplicates are dropped */
 	if (pqueue_insert(queue->q, item) == NULL)
 		{
 		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
 		if (rdata->rbuf.buf != NULL)
 			OPENSSL_free(rdata->rbuf.buf);
 		OPENSSL_free(rdata);
 		pitem_free(item);
 		return(-1);
 		}
 
 	return(1);
 	}
 
 
 static int
 dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
     {
     pitem *item;
 
     item = pqueue_pop(queue->q);
     if (item)
         {
         dtls1_copy_record(s, item);
 
         OPENSSL_free(item->data);
 		pitem_free(item);
 
         return(1);
         }
 
     return(0);
     }
 
 
 /* retrieve a buffered record that belongs to the new epoch, i.e., not processed 
  * yet */
 #define dtls1_get_unprocessed_record(s) \
                    dtls1_retrieve_buffered_record((s), \
                    &((s)->d1->unprocessed_rcds))
 
 /* retrieve a buffered record that belongs to the current epoch, ie, processed */
 #define dtls1_get_processed_record(s) \
                    dtls1_retrieve_buffered_record((s), \
                    &((s)->d1->processed_rcds))
 
 static int
 dtls1_process_buffered_records(SSL *s)
     {
     pitem *item;
     
     item = pqueue_peek(s->d1->unprocessed_rcds.q);
     if (item)
         {
         /* Check if epoch is current. */
         if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
             return(1);  /* Nothing to do. */
         
         /* Process all the records. */
         while (pqueue_peek(s->d1->unprocessed_rcds.q))
             {
             dtls1_get_unprocessed_record(s);
             if ( ! dtls1_process_record(s))
                 return(0);
             if(dtls1_buffer_record(s, &(s->d1->processed_rcds),
                 s->s3->rrec.seq_num)<0)
                 return -1;
             }
         }
 
     /* sync epoch numbers once all the unprocessed records 
      * have been processed */
     s->d1->processed_rcds.epoch = s->d1->r_epoch;
     s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
 
     return(1);
     }
 
 
 #if 0
 
 static int
 dtls1_get_buffered_record(SSL *s)
 	{
 	pitem *item;
 	PQ_64BIT priority = 
 		(((PQ_64BIT)s->d1->handshake_read_seq) << 32) | 
 		((PQ_64BIT)s->d1->r_msg_hdr.frag_off);
 	
 	if ( ! SSL_in_init(s))  /* if we're not (re)negotiating, 
 							   nothing buffered */
 		return 0;
 
 
 	item = pqueue_peek(s->d1->rcvd_records);
 	if (item && item->priority == priority)
 		{
 		/* Check if we've received the record of interest.  It must be
 		 * a handshake record, since data records as passed up without
 		 * buffering */
 		DTLS1_RECORD_DATA *rdata;
 		item = pqueue_pop(s->d1->rcvd_records);
 		rdata = (DTLS1_RECORD_DATA *)item->data;
 		
 		if (s->s3->rbuf.buf != NULL)
 			OPENSSL_free(s->s3->rbuf.buf);
 		
 		s->packet = rdata->packet;
 		s->packet_length = rdata->packet_length;
 		memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
 		memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
 		
 		OPENSSL_free(item->data);
 		pitem_free(item);
 		
 		/* s->d1->next_expected_seq_num++; */
 		return(1);
 		}
 	
 	return 0;
 	}
 
 #endif
 
 static int
 dtls1_process_record(SSL *s)
 {
 	int i,al;
 	int enc_err;
 	SSL_SESSION *sess;
 	SSL3_RECORD *rr;
 	unsigned int mac_size, orig_len;
 	unsigned char md[EVP_MAX_MD_SIZE];
 
 	rr= &(s->s3->rrec);
 	sess = s->session;
 
 	/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
 	 * and we have that many bytes in s->packet
 	 */
 	rr->input= &(s->packet[DTLS1_RT_HEADER_LENGTH]);
 
 	/* ok, we can now read from 's->packet' data into 'rr'
 	 * rr->input points at rr->length bytes, which
 	 * need to be copied into rr->data by either
 	 * the decryption or by the decompression
 	 * When the data is 'copied' into the rr->data buffer,
 	 * rr->input will be pointed at the new buffer */ 
 
 	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
 	 * rr->length bytes of encrypted compressed stuff. */
 
 	/* check is not needed I believe */
 	if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
 		{
 		al=SSL_AD_RECORD_OVERFLOW;
 		SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
 		goto f_err;
 		}
 
 	/* decrypt in place in 'rr->input' */
 	rr->data=rr->input;
 
 	enc_err = s->method->ssl3_enc->enc(s,0);
 	/* enc_err is:
 	 *    0: (in non-constant time) if the record is publically invalid.
 	 *    1: if the padding is valid
 	 *    -1: if the padding is invalid */
 	if (enc_err == 0)
 		{
 		/* For DTLS we simply ignore bad packets. */
 		rr->length = 0;
 		s->packet_length = 0;
 		goto err;
 		}
 
 #ifdef TLS_DEBUG
 printf("dec %d\n",rr->length);
 { unsigned int z; for (z=0; zlength; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
 printf("\n");
 #endif
 
 	/* r->length is now the compressed data plus mac */
 	if ((sess != NULL) &&
 	    (s->enc_read_ctx != NULL) &&
 	    (EVP_MD_CTX_md(s->read_hash) != NULL))
 		{
 		/* s->read_hash != NULL => mac_size != -1 */
 		unsigned char *mac = NULL;
 		unsigned char mac_tmp[EVP_MAX_MD_SIZE];
 		mac_size=EVP_MD_CTX_size(s->read_hash);
 		OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
 
 		/* kludge: *_cbc_remove_padding passes padding length in rr->type */
 		orig_len = rr->length+((unsigned int)rr->type>>8);
 
 		/* orig_len is the length of the record before any padding was
 		 * removed. This is public information, as is the MAC in use,
 		 * therefore we can safely process the record in a different
 		 * amount of time if it's too short to possibly contain a MAC.
 		 */
 		if (orig_len < mac_size ||
 		    /* CBC records must have a padding length byte too. */
 		    (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
 		     orig_len < mac_size+1))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 
 		if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE)
 			{
 			/* We update the length so that the TLS header bytes
 			 * can be constructed correctly but we need to extract
 			 * the MAC in constant time from within the record,
 			 * without leaking the contents of the padding bytes.
 			 * */
 			mac = mac_tmp;
 			ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
 			rr->length -= mac_size;
 			}
 		else
 			{
 			/* In this case there's no padding, so |orig_len|
 			 * equals |rec->length| and we checked that there's
 			 * enough bytes for |mac_size| above. */
 			rr->length -= mac_size;
 			mac = &rr->data[rr->length];
 			}
 
 		i=s->method->ssl3_enc->mac(s,md,0 /* not send */);
 		if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
 			enc_err = -1;
 		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
 			enc_err = -1;
 		}
 
 	if (enc_err < 0)
 		{
 		/* decryption failed, silently discard message */
 		rr->length = 0;
 		s->packet_length = 0;
 		goto err;
 		}
 
 	/* r->length is now just compressed */
 	if (s->expand != NULL)
 		{
 		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH)
 			{
 			al=SSL_AD_RECORD_OVERFLOW;
 			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
 			goto f_err;
 			}
 		if (!ssl3_do_uncompress(s))
 			{
 			al=SSL_AD_DECOMPRESSION_FAILURE;
 			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_BAD_DECOMPRESSION);
 			goto f_err;
 			}
 		}
 
 	if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH)
 		{
 		al=SSL_AD_RECORD_OVERFLOW;
 		SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
 		goto f_err;
 		}
 
 	rr->off=0;
 	/* So at this point the following is true
 	 * ssl->s3->rrec.type 	is the type of record
 	 * ssl->s3->rrec.length	== number of bytes in record
 	 * ssl->s3->rrec.off	== offset to first valid byte
 	 * ssl->s3->rrec.data	== where to take bytes from, increment
 	 *			   after use :-).
 	 */
 
 	/* we have pulled in a full packet so zero things */
 	s->packet_length=0;
 	return(1);
 
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(0);
 }
 
 
 /* Call this to get a new input record.
  * It will return <= 0 if more data is needed, normally due to an error
  * or non-blocking IO.
  * When it finishes, one packet has been decoded and can be found in
  * ssl->s3->rrec.type    - is the type of record
  * ssl->s3->rrec.data, 	 - data
  * ssl->s3->rrec.length, - number of bytes
  */
 /* used only by dtls1_read_bytes */
 int dtls1_get_record(SSL *s)
 	{
 	int ssl_major,ssl_minor;
 	int i,n;
 	SSL3_RECORD *rr;
 	unsigned char *p = NULL;
 	unsigned short version;
 	DTLS1_BITMAP *bitmap;
 	unsigned int is_next_epoch;
 
 	rr= &(s->s3->rrec);
 
 	/* The epoch may have changed.  If so, process all the
 	 * pending records.  This is a non-blocking operation. */
 	if(dtls1_process_buffered_records(s)<0)
 		return -1;
 
 	/* if we're renegotiating, then there may be buffered records */
 	if (dtls1_get_processed_record(s))
 		return 1;
 
 	/* get something from the wire */
 again:
 	/* check if we have the header */
 	if (	(s->rstate != SSL_ST_READ_BODY) ||
 		(s->packet_length < DTLS1_RT_HEADER_LENGTH)) 
 		{
 		n=ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
 		/* read timeout is handled by dtls1_read_bytes */
 		if (n <= 0) return(n); /* error or non-blocking */
 
 		/* this packet contained a partial record, dump it */
 		if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
 			{
 			s->packet_length = 0;
 			goto again;
 			}
 
 		s->rstate=SSL_ST_READ_BODY;
 
 		p=s->packet;
 
 		/* Pull apart the header into the DTLS1_RECORD */
 		rr->type= *(p++);
 		ssl_major= *(p++);
 		ssl_minor= *(p++);
 		version=(ssl_major<<8)|ssl_minor;
 
 		/* sequence number is 64 bits, with top 2 bytes = epoch */ 
 		n2s(p,rr->epoch);
 
 		memcpy(&(s->s3->read_sequence[2]), p, 6);
 		p+=6;
 
 		n2s(p,rr->length);
 
 		/* Lets check version */
 		if (!s->first_packet)
 			{
 			if (version != s->version)
 				{
 				/* unexpected version, silently discard */
 				rr->length = 0;
 				s->packet_length = 0;
 				goto again;
 				}
 			}
 
 		if ((version & 0xff00) != (s->version & 0xff00))
 			{
 			/* wrong version, silently discard record */
 			rr->length = 0;
 			s->packet_length = 0;
 			goto again;
 			}
 
 		if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
 			{
 			/* record too long, silently discard it */
 			rr->length = 0;
 			s->packet_length = 0;
 			goto again;
 			}
 
 		/* now s->rstate == SSL_ST_READ_BODY */
 		}
 
 	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */
 
 	if (rr->length > s->packet_length-DTLS1_RT_HEADER_LENGTH)
 		{
 		/* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
 		i=rr->length;
 		n=ssl3_read_n(s,i,i,1);
 		/* this packet contained a partial record, dump it */
 		if ( n != i)
 			{
 			rr->length = 0;
 			s->packet_length = 0;
 			goto again;
 			}
 
 		/* now n == rr->length,
 		 * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */
 		}
 	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
 
 	/* match epochs.  NULL means the packet is dropped on the floor */
 	bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
 	if ( bitmap == NULL)
 		{
 		rr->length = 0;
 		s->packet_length = 0;  /* dump this record */
 		goto again;   /* get another record */
 		}
 
 #ifndef OPENSSL_NO_SCTP
 	/* Only do replay check if no SCTP bio */
 	if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
   		{
 #endif
 		/* Check whether this is a repeat, or aged record.
 		 * Don't check if we're listening and this message is
 		 * a ClientHello. They can look as if they're replayed,
 		 * since they arrive from different connections and
 		 * would be dropped unnecessarily.
 		 */
 		if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
 		    s->packet_length > DTLS1_RT_HEADER_LENGTH &&
 		    s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
 		    !dtls1_record_replay_check(s, bitmap))
 			{
 			rr->length = 0;
 			s->packet_length=0; /* dump this record */
 			goto again;     /* get another record */
 			}
 #ifndef OPENSSL_NO_SCTP
   		}
 #endif
 
 	/* just read a 0 length packet */
 	if (rr->length == 0) goto again;
 
 	/* If this record is from the next epoch (either HM or ALERT),
 	 * and a handshake is currently in progress, buffer it since it
 	 * cannot be processed at this time. However, do not buffer
 	 * anything while listening.
 	 */
 	if (is_next_epoch)
 		{
 		if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen)
 			{
 			if(dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num)<0)
 				return -1;
 			dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
 			}
 		rr->length = 0;
 		s->packet_length = 0;
 		goto again;
 		}
 
 	if (!dtls1_process_record(s))
 		{
 		rr->length = 0;
 		s->packet_length = 0;  /* dump this record */
 		goto again;   /* get another record */
 		}
 	dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
 
 	return(1);
 
 	}
 
 /* Return up to 'len' payload bytes received in 'type' records.
  * 'type' is one of the following:
  *
  *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
  *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
  *   -  0 (during a shutdown, no data has to be returned)
  *
  * If we don't have stored data to work from, read a SSL/TLS record first
  * (possibly multiple records if we still don't have anything to return).
  *
  * This function must handle any surprises the peer may have for us, such as
  * Alert records (e.g. close_notify), ChangeCipherSpec records (not really
  * a surprise, but handled as if it were), or renegotiation requests.
  * Also if record payloads contain fragments too small to process, we store
  * them until there is enough for the respective protocol (the record protocol
  * may use arbitrary fragmentation and even interleaving):
  *     Change cipher spec protocol
  *             just 1 byte needed, no need for keeping anything stored
  *     Alert protocol
  *             2 bytes needed (AlertLevel, AlertDescription)
  *     Handshake protocol
  *             4 bytes needed (HandshakeType, uint24 length) -- we just have
  *             to detect unexpected Client Hello and Hello Request messages
  *             here, anything else is handled by higher layers
  *     Application data protocol
  *             none of our business
  */
 int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
 	{
 	int al,i,j,ret;
 	unsigned int n;
 	SSL3_RECORD *rr;
 	void (*cb)(const SSL *ssl,int type2,int val)=NULL;
 
 	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
 		if (!ssl3_setup_buffers(s))
 			return(-1);
 
     /* XXX: check what the second '&& type' is about */
 	if ((type && (type != SSL3_RT_APPLICATION_DATA) && 
 		(type != SSL3_RT_HANDSHAKE) && type) ||
 	    (peek && (type != SSL3_RT_APPLICATION_DATA)))
 		{
 		SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
 		return -1;
 		}
 
 	/* check whether there's a handshake message (client hello?) waiting */
 	if ( (ret = have_handshake_fragment(s, type, buf, len, peek)))
 		return ret;
 
 	/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
 
 #ifndef OPENSSL_NO_SCTP
 	/* Continue handshake if it had to be interrupted to read
 	 * app data with SCTP.
 	 */
 	if ((!s->in_handshake && SSL_in_init(s)) ||
 	    (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
 	     (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK) &&
 	     s->s3->in_read_app_data != 2))
 #else
 	if (!s->in_handshake && SSL_in_init(s))
 #endif
 		{
 		/* type == SSL3_RT_APPLICATION_DATA */
 		i=s->handshake_func(s);
 		if (i < 0) return(i);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
 			return(-1);
 			}
 		}
 
 start:
 	s->rwstate=SSL_NOTHING;
 
 	/* s->s3->rrec.type	    - is the type of record
 	 * s->s3->rrec.data,    - data
 	 * s->s3->rrec.off,     - offset into 'data' for next read
 	 * s->s3->rrec.length,  - number of bytes. */
 	rr = &(s->s3->rrec);
 
 	/* We are not handshaking and have no data yet,
 	 * so process data buffered during the last handshake
 	 * in advance, if any.
 	 */
 	if (s->state == SSL_ST_OK && rr->length == 0)
 		{
 		pitem *item;
 		item = pqueue_pop(s->d1->buffered_app_data.q);
 		if (item)
 			{
 #ifndef OPENSSL_NO_SCTP
 			/* Restore bio_dgram_sctp_rcvinfo struct */
 			if (BIO_dgram_is_sctp(SSL_get_rbio(s)))
 				{
 				DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *) item->data;
 				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
 				}
 #endif
 
 			dtls1_copy_record(s, item);
 
 			OPENSSL_free(item->data);
 			pitem_free(item);
 			}
 		}
 
 	/* Check for timeout */
 	if (dtls1_handle_timeout(s) > 0)
 		goto start;
 
 	/* get new packet if necessary */
 	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
 		{
 		ret=dtls1_get_record(s);
 		if (ret <= 0) 
 			{
 			ret = dtls1_read_failed(s, ret);
 			/* anything other than a timeout is an error */
 			if (ret <= 0)  
 				return(ret);
 			else
 				goto start;
 			}
 		}
 
 	if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE)
 		{
 		rr->length = 0;
 		goto start;
 		}
 
 	/* we now have a packet which can be read and processed */
 
 	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
 	                               * reset by ssl3_get_finished */
 		&& (rr->type != SSL3_RT_HANDSHAKE))
 		{
 		/* We now have application data between CCS and Finished.
 		 * Most likely the packets were reordered on their way, so
 		 * buffer the application data for later processing rather
 		 * than dropping the connection.
 		 */
 		if(dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num)<0)
 			{
 			SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 		rr->length = 0;
 		goto start;
 		}
 
 	/* If the other end has shut down, throw anything we read away
 	 * (even in 'peek' mode) */
 	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
 		{
 		rr->length=0;
 		s->rwstate=SSL_NOTHING;
 		return(0);
 		}
 
 
 	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
 		{
 		/* make sure that we are not getting application data when we
 		 * are doing a handshake for the first time */
 		if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
 			(s->enc_read_ctx == NULL))
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
 			goto f_err;
 			}
 
 		if (len <= 0) return(len);
 
 		if ((unsigned int)len > rr->length)
 			n = rr->length;
 		else
 			n = (unsigned int)len;
 
 		memcpy(buf,&(rr->data[rr->off]),n);
 		if (!peek)
 			{
 			rr->length-=n;
 			rr->off+=n;
 			if (rr->length == 0)
 				{
 				s->rstate=SSL_ST_READ_HEADER;
 				rr->off=0;
 				}
 			}
 
 #ifndef OPENSSL_NO_SCTP
 			/* We were about to renegotiate but had to read
 			 * belated application data first, so retry.
 			 */
 			if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
 			    rr->type == SSL3_RT_APPLICATION_DATA &&
 			    (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK))
 				{
 				s->rwstate=SSL_READING;
 				BIO_clear_retry_flags(SSL_get_rbio(s));
 				BIO_set_retry_read(SSL_get_rbio(s));
 				}
 
 			/* We might had to delay a close_notify alert because
 			 * of reordered app data. If there was an alert and there
 			 * is no message to read anymore, finally set shutdown.
 			 */
 			if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
 			    s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
 				{
 				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
 				return(0);
 				}
 #endif			
 		return(n);
 		}
 
 
 	/* If we get here, then type != rr->type; if we have a handshake
 	 * message, then it was unexpected (Hello Request or Client Hello). */
 
 	/* In case of record types for which we have 'fragment' storage,
 	 * fill that so that we can process the data at a fixed place.
 	 */
 		{
 		unsigned int k, dest_maxlen = 0;
 		unsigned char *dest = NULL;
 		unsigned int *dest_len = NULL;
 
 		if (rr->type == SSL3_RT_HANDSHAKE)
 			{
 			dest_maxlen = sizeof s->d1->handshake_fragment;
 			dest = s->d1->handshake_fragment;
 			dest_len = &s->d1->handshake_fragment_len;
 			}
 		else if (rr->type == SSL3_RT_ALERT)
 			{
 			dest_maxlen = sizeof(s->d1->alert_fragment);
 			dest = s->d1->alert_fragment;
 			dest_len = &s->d1->alert_fragment_len;
 			}
 #ifndef OPENSSL_NO_HEARTBEATS
 		else if (rr->type == TLS1_RT_HEARTBEAT)
 			{
 			dtls1_process_heartbeat(s);
 
 			/* Exit and notify application to read again */
 			rr->length = 0;
 			s->rwstate=SSL_READING;
 			BIO_clear_retry_flags(SSL_get_rbio(s));
 			BIO_set_retry_read(SSL_get_rbio(s));
 			return(-1);
 			}
 #endif
 		/* else it's a CCS message, or application data or wrong */
 		else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
 			{
 			/* Application data while renegotiating
 			 * is allowed. Try again reading.
 			 */
 			if (rr->type == SSL3_RT_APPLICATION_DATA)
 				{
 				BIO *bio;
 				s->s3->in_read_app_data=2;
 				bio=SSL_get_rbio(s);
 				s->rwstate=SSL_READING;
 				BIO_clear_retry_flags(bio);
 				BIO_set_retry_read(bio);
 				return(-1);
 				}
 
 			/* Not certain if this is the right error handling */
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
 			goto f_err;
 			}
 
 		if (dest_maxlen > 0)
 			{
             /* XDTLS:  In a pathalogical case, the Client Hello
              *  may be fragmented--don't always expect dest_maxlen bytes */
 			if ( rr->length < dest_maxlen)
 				{
 #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 				/*
 				 * for normal alerts rr->length is 2, while
 				 * dest_maxlen is 7 if we were to handle this
 				 * non-existing alert...
 				 */
 				FIX ME
 #endif
 				s->rstate=SSL_ST_READ_HEADER;
 				rr->length = 0;
 				goto start;
 				}
 
 			/* now move 'n' bytes: */
 			for ( k = 0; k < dest_maxlen; k++)
 				{
 				dest[k] = rr->data[rr->off++];
 				rr->length--;
 				}
 			*dest_len = dest_maxlen;
 			}
 		}
 
 	/* s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
 	 * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
 	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
 
 	/* If we are a client, check for an incoming 'Hello Request': */
 	if ((!s->server) &&
 		(s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
 		(s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
 		(s->session != NULL) && (s->session->cipher != NULL))
 		{
 		s->d1->handshake_fragment_len = 0;
 
 		if ((s->d1->handshake_fragment[1] != 0) ||
 			(s->d1->handshake_fragment[2] != 0) ||
 			(s->d1->handshake_fragment[3] != 0))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
-			goto err;
+			goto f_err;
 			}
 
 		/* no need to check sequence number on HELLO REQUEST messages */
 
 		if (s->msg_callback)
 			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
 				s->d1->handshake_fragment, 4, s, s->msg_callback_arg);
 
 		if (SSL_is_init_finished(s) &&
 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
 			!s->s3->renegotiate)
 			{
 			s->d1->handshake_read_seq++;
 			s->new_session = 1;
 			ssl3_renegotiate(s);
 			if (ssl3_renegotiate_check(s))
 				{
 				i=s->handshake_func(s);
 				if (i < 0) return(i);
 				if (i == 0)
 					{
 					SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
 					return(-1);
 					}
 
 				if (!(s->mode & SSL_MODE_AUTO_RETRY))
 					{
 					if (s->s3->rbuf.left == 0) /* no read-ahead left? */
 						{
 						BIO *bio;
 						/* In the case where we try to read application data,
 						 * but we trigger an SSL handshake, we return -1 with
 						 * the retry option set.  Otherwise renegotiation may
 						 * cause nasty problems in the blocking world */
 						s->rwstate=SSL_READING;
 						bio=SSL_get_rbio(s);
 						BIO_clear_retry_flags(bio);
 						BIO_set_retry_read(bio);
 						return(-1);
 						}
 					}
 				}
 			}
 		/* we either finished a handshake or ignored the request,
 		 * now try again to obtain the (application) data we were asked for */
 		goto start;
 		}
 
 	if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH)
 		{
 		int alert_level = s->d1->alert_fragment[0];
 		int alert_descr = s->d1->alert_fragment[1];
 
 		s->d1->alert_fragment_len = 0;
 
 		if (s->msg_callback)
 			s->msg_callback(0, s->version, SSL3_RT_ALERT, 
 				s->d1->alert_fragment, 2, s, s->msg_callback_arg);
 
 		if (s->info_callback != NULL)
 			cb=s->info_callback;
 		else if (s->ctx->info_callback != NULL)
 			cb=s->ctx->info_callback;
 
 		if (cb != NULL)
 			{
 			j = (alert_level << 8) | alert_descr;
 			cb(s, SSL_CB_READ_ALERT, j);
 			}
 
 		if (alert_level == 1) /* warning */
 			{
 			s->s3->warn_alert = alert_descr;
 			if (alert_descr == SSL_AD_CLOSE_NOTIFY)
 				{
 #ifndef OPENSSL_NO_SCTP
 				/* With SCTP and streams the socket may deliver app data
 				 * after a close_notify alert. We have to check this
 				 * first so that nothing gets discarded.
 				 */
 				if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
 					BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
 					{
 					s->d1->shutdown_received = 1;
 					s->rwstate=SSL_READING;
 					BIO_clear_retry_flags(SSL_get_rbio(s));
 					BIO_set_retry_read(SSL_get_rbio(s));
 					return -1;
 					}
 #endif
 				s->shutdown |= SSL_RECEIVED_SHUTDOWN;
 				return(0);
 				}
 #if 0
             /* XXX: this is a possible improvement in the future */
 			/* now check if it's a missing record */
 			if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
 				{
 				unsigned short seq;
 				unsigned int frag_off;
 				unsigned char *p = &(s->d1->alert_fragment[2]);
 
 				n2s(p, seq);
 				n2l3(p, frag_off);
 
 				dtls1_retransmit_message(s,
 										 dtls1_get_queue_priority(frag->msg_header.seq, 0),
 										 frag_off, &found);
 				if ( ! found  && SSL_in_init(s))
 					{
 					/* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
 					/* requested a message not yet sent, 
 					   send an alert ourselves */
 					ssl3_send_alert(s,SSL3_AL_WARNING,
 						DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
 					}
 				}
 #endif
 			}
 		else if (alert_level == 2) /* fatal */
 			{
 			char tmp[16];
 
 			s->rwstate=SSL_NOTHING;
 			s->s3->fatal_alert = alert_descr;
 			SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
 			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
 			ERR_add_error_data(2,"SSL alert number ",tmp);
 			s->shutdown|=SSL_RECEIVED_SHUTDOWN;
 			SSL_CTX_remove_session(s->ctx,s->session);
 			return(0);
 			}
 		else
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
 			goto f_err;
 			}
 
 		goto start;
 		}
 
 	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
 		{
 		s->rwstate=SSL_NOTHING;
 		rr->length=0;
 		return(0);
 		}
 
 	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
 		{
 		struct ccs_header_st ccs_hdr;
 		unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
 
 		dtls1_get_ccs_header(rr->data, &ccs_hdr);
 
 		if (s->version == DTLS1_BAD_VER)
 			ccs_hdr_len = 3;
 
 		/* 'Change Cipher Spec' is just a single byte, so we know
 		 * exactly what the record payload has to look like */
 		/* XDTLS: check that epoch is consistent */
 		if (	(rr->length != ccs_hdr_len) || 
 			(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
 			{
 			i=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
 			goto err;
 			}
 
 		rr->length=0;
 
 		if (s->msg_callback)
 			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
 				rr->data, 1, s, s->msg_callback_arg);
 
 		/* We can't process a CCS now, because previous handshake
 		 * messages are still missing, so just drop it.
 		 */
 		if (!s->d1->change_cipher_spec_ok)
 			{
 			goto start;
 			}
 
 		s->d1->change_cipher_spec_ok = 0;
 
 		s->s3->change_cipher_spec=1;
 		if (!ssl3_do_change_cipher_spec(s))
 			goto err;
 
 		/* do this whenever CCS is processed */
 		dtls1_reset_seq_numbers(s, SSL3_CC_READ);
 
 		if (s->version == DTLS1_BAD_VER)
 			s->d1->handshake_read_seq++;
 
 #ifndef OPENSSL_NO_SCTP
 		/* Remember that a CCS has been received,
 		 * so that an old key of SCTP-Auth can be
 		 * deleted when a CCS is sent. Will be ignored
 		 * if no SCTP is used
 		 */
 		BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
 #endif
 
 		goto start;
 		}
 
 	/* Unexpected handshake message (Client Hello, or protocol violation) */
 	if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && 
 		!s->in_handshake)
 		{
 		struct hm_header_st msg_hdr;
 		
 		/* this may just be a stale retransmit */
 		dtls1_get_message_header(rr->data, &msg_hdr);
 		if( rr->epoch != s->d1->r_epoch)
 			{
 			rr->length = 0;
 			goto start;
 			}
 
 		/* If we are server, we may have a repeated FINISHED of the
 		 * client here, then retransmit our CCS and FINISHED.
 		 */
 		if (msg_hdr.type == SSL3_MT_FINISHED)
 			{
 			if (dtls1_check_timeout_num(s) < 0)
 				return -1;
 
 			dtls1_retransmit_buffered_messages(s);
 			rr->length = 0;
 			goto start;
 			}
 
 		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
 			{
 #if 0 /* worked only because C operator preferences are not as expected (and
        * because this is not really needed for clients except for detecting
        * protocol violations): */
 			s->state=SSL_ST_BEFORE|(s->server)
 				?SSL_ST_ACCEPT
 				:SSL_ST_CONNECT;
 #else
 			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
 #endif
 			s->renegotiate=1;
 			s->new_session=1;
 			}
 		i=s->handshake_func(s);
 		if (i < 0) return(i);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
 			return(-1);
 			}
 
 		if (!(s->mode & SSL_MODE_AUTO_RETRY))
 			{
 			if (s->s3->rbuf.left == 0) /* no read-ahead left? */
 				{
 				BIO *bio;
 				/* In the case where we try to read application data,
 				 * but we trigger an SSL handshake, we return -1 with
 				 * the retry option set.  Otherwise renegotiation may
 				 * cause nasty problems in the blocking world */
 				s->rwstate=SSL_READING;
 				bio=SSL_get_rbio(s);
 				BIO_clear_retry_flags(bio);
 				BIO_set_retry_read(bio);
 				return(-1);
 				}
 			}
 		goto start;
 		}
 
 	switch (rr->type)
 		{
 	default:
 #ifndef OPENSSL_NO_TLS
 		/* TLS just ignores unknown message types */
 		if (s->version == TLS1_VERSION)
 			{
 			rr->length = 0;
 			goto start;
 			}
 #endif
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
 		goto f_err;
 	case SSL3_RT_CHANGE_CIPHER_SPEC:
 	case SSL3_RT_ALERT:
 	case SSL3_RT_HANDSHAKE:
 		/* we already handled all of these, with the possible exception
 		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
 		 * should not happen when type != rr->type */
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_DTLS1_READ_BYTES,ERR_R_INTERNAL_ERROR);
 		goto f_err;
 	case SSL3_RT_APPLICATION_DATA:
 		/* At this point, we were expecting handshake data,
 		 * but have application data.  If the library was
 		 * running inside ssl3_read() (i.e. in_read_app_data
 		 * is set) and it makes sense to read application data
 		 * at this point (session renegotiation not yet started),
 		 * we will indulge it.
 		 */
 		if (s->s3->in_read_app_data &&
 			(s->s3->total_renegotiations != 0) &&
 			((
 				(s->state & SSL_ST_CONNECT) &&
 				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
 				(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
 				) || (
 					(s->state & SSL_ST_ACCEPT) &&
 					(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
 					(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
 					)
 				))
 			{
 			s->s3->in_read_app_data=2;
 			return(-1);
 			}
 		else
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
 			goto f_err;
 			}
 		}
 	/* not reached */
 
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(-1);
 	}
 
 int
 dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
 	{
 	int i;
 
 #ifndef OPENSSL_NO_SCTP
 		/* Check if we have to continue an interrupted handshake
 		 * for reading belated app data with SCTP.
 		 */
 		if ((SSL_in_init(s) && !s->in_handshake) ||
 		    (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
 		     (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)))
 #else
 		if (SSL_in_init(s) && !s->in_handshake)
 #endif
 		{
 		i=s->handshake_func(s);
 		if (i < 0) return(i);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
 			return -1;
 			}
 		}
 
 	if (len > SSL3_RT_MAX_PLAIN_LENGTH)
 		{
 			SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_DTLS_MESSAGE_TOO_BIG);
 			return -1;
 		}
 
 	i = dtls1_write_bytes(s, type, buf_, len);
 	return i;
 	}
 
 
 	/* this only happens when a client hello is received and a handshake 
 	 * is started. */
 static int
 have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
 	int len, int peek)
 	{
 	
 	if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
 		/* (partially) satisfy request from storage */
 		{
 		unsigned char *src = s->d1->handshake_fragment;
 		unsigned char *dst = buf;
 		unsigned int k,n;
 		
 		/* peek == 0 */
 		n = 0;
 		while ((len > 0) && (s->d1->handshake_fragment_len > 0))
 			{
 			*dst++ = *src++;
 			len--; s->d1->handshake_fragment_len--;
 			n++;
 			}
 		/* move any remaining fragment bytes: */
 		for (k = 0; k < s->d1->handshake_fragment_len; k++)
 			s->d1->handshake_fragment[k] = *src++;
 		return n;
 		}
 	
 	return 0;
 	}
 
 
 
 
 /* Call this to write data in records of type 'type'
  * It will return <= 0 if not all data has been sent or non-blocking IO.
  */
 int dtls1_write_bytes(SSL *s, int type, const void *buf, int len)
 	{
 	int i;
 
 	OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
 	s->rwstate=SSL_NOTHING;
 	i=do_dtls1_write(s, type, buf, len, 0);
 	return i;
 	}
 
 int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment)
 	{
 	unsigned char *p,*pseq;
 	int i,mac_size,clear=0;
 	int prefix_len = 0;
 	SSL3_RECORD *wr;
 	SSL3_BUFFER *wb;
 	SSL_SESSION *sess;
 	int bs;
 
 	/* first check if there is a SSL3_BUFFER still being written
 	 * out.  This will happen with non blocking IO */
 	if (s->s3->wbuf.left != 0)
 		{
 		OPENSSL_assert(0); /* XDTLS:  want to see if we ever get here */
 		return(ssl3_write_pending(s,type,buf,len));
 		}
 
 	/* If we have an alert to send, lets send it */
 	if (s->s3->alert_dispatch)
 		{
 		i=s->method->ssl_dispatch_alert(s);
 		if (i <= 0)
 			return(i);
 		/* if it went, fall through and send more stuff */
 		}
 
 	if (len == 0 && !create_empty_fragment)
 		return 0;
 
 	wr= &(s->s3->wrec);
 	wb= &(s->s3->wbuf);
 	sess=s->session;
 
 	if (	(sess == NULL) ||
 		(s->enc_write_ctx == NULL) ||
 		(EVP_MD_CTX_md(s->write_hash) == NULL))
 		clear=1;
 
 	if (clear)
 		mac_size=0;
 	else
 		{
 		mac_size=EVP_MD_CTX_size(s->write_hash);
 		if (mac_size < 0)
 			goto err;
 		}
 
 	/* DTLS implements explicit IV, so no need for empty fragments */
 #if 0
 	/* 'create_empty_fragment' is true only when this function calls itself */
 	if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
 	    && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
 		{
 		/* countermeasure against known-IV weakness in CBC ciphersuites
 		 * (see http://www.openssl.org/~bodo/tls-cbc.txt) 
 		 */
 
 		if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA)
 			{
 			/* recursive function call with 'create_empty_fragment' set;
 			 * this prepares and buffers the data for an empty fragment
 			 * (these 'prefix_len' bytes are sent out later
 			 * together with the actual payload) */
 			prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1);
 			if (prefix_len <= 0)
 				goto err;
 
 			if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE)
 				{
 				/* insufficient space */
 				SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			}
 		
 		s->s3->empty_fragment_done = 1;
 		}
 #endif
 	p = wb->buf + prefix_len;
 
 	/* write the header */
 
 	*(p++)=type&0xff;
 	wr->type=type;
 
 	*(p++)=(s->version>>8);
 	*(p++)=s->version&0xff;
 
 	/* field where we are to write out packet epoch, seq num and len */
 	pseq=p; 
 	p+=10;
 
 	/* lets setup the record stuff. */
 
 	/* Make space for the explicit IV in case of CBC.
 	 * (this is a bit of a boundary violation, but what the heck).
 	 */
 	if ( s->enc_write_ctx && 
 		(EVP_CIPHER_mode( s->enc_write_ctx->cipher ) & EVP_CIPH_CBC_MODE))
 		bs = EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
 	else
 		bs = 0;
 
 	wr->data=p + bs;  /* make room for IV in case of CBC */
 	wr->length=(int)len;
 	wr->input=(unsigned char *)buf;
 
 	/* we now 'read' from wr->input, wr->length bytes into
 	 * wr->data */
 
 	/* first we compress */
 	if (s->compress != NULL)
 		{
 		if (!ssl3_do_compress(s))
 			{
 			SSLerr(SSL_F_DO_DTLS1_WRITE,SSL_R_COMPRESSION_FAILURE);
 			goto err;
 			}
 		}
 	else
 		{
 		memcpy(wr->data,wr->input,wr->length);
 		wr->input=wr->data;
 		}
 
 	/* we should still have the output to wr->data and the input
 	 * from wr->input.  Length should be wr->length.
 	 * wr->data still points in the wb->buf */
 
 	if (mac_size != 0)
 		{
 		if(s->method->ssl3_enc->mac(s,&(p[wr->length + bs]),1) < 0)
 			goto err;
 		wr->length+=mac_size;
 		}
 
 	/* this is true regardless of mac size */
 	wr->input=p;
 	wr->data=p;
 
 
 	/* ssl3_enc can only have an error on read */
 	if (bs)	/* bs != 0 in case of CBC */
 		{
 		RAND_pseudo_bytes(p,bs);
 		/* master IV and last CBC residue stand for
 		 * the rest of randomness */
 		wr->length += bs;
 		}
 
 	if(s->method->ssl3_enc->enc(s,1) < 1) goto err;
 
 	/* record length after mac and block padding */
 /*	if (type == SSL3_RT_APPLICATION_DATA ||
 	(type == SSL3_RT_ALERT && ! SSL_in_init(s))) */
 	
 	/* there's only one epoch between handshake and app data */
 	
 	s2n(s->d1->w_epoch, pseq);
 
 	/* XDTLS: ?? */
 /*	else
 	s2n(s->d1->handshake_epoch, pseq); */
 
 	memcpy(pseq, &(s->s3->write_sequence[2]), 6);
 	pseq+=6;
 	s2n(wr->length,pseq);
 
 	/* we should now have
 	 * wr->data pointing to the encrypted data, which is
 	 * wr->length long */
 	wr->type=type; /* not needed but helps for debugging */
 	wr->length+=DTLS1_RT_HEADER_LENGTH;
 
 #if 0  /* this is now done at the message layer */
 	/* buffer the record, making it easy to handle retransmits */
 	if ( type == SSL3_RT_HANDSHAKE || type == SSL3_RT_CHANGE_CIPHER_SPEC)
 		dtls1_buffer_record(s, wr->data, wr->length, 
 			*((PQ_64BIT *)&(s->s3->write_sequence[0])));
 #endif
 
 	ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
 
 	if (create_empty_fragment)
 		{
 		/* we are in a recursive call;
 		 * just return the length, don't write out anything here
 		 */
 		return wr->length;
 		}
 
 	/* now let's set up wb */
 	wb->left = prefix_len + wr->length;
 	wb->offset = 0;
 
 	/* memorize arguments so that ssl3_write_pending can detect bad write retries later */
 	s->s3->wpend_tot=len;
 	s->s3->wpend_buf=buf;
 	s->s3->wpend_type=type;
 	s->s3->wpend_ret=len;
 
 	/* we now just need to write the buffer */
 	return ssl3_write_pending(s,type,buf,len);
 err:
 	return -1;
 	}
 
 
 
 static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
 	{
 	int cmp;
 	unsigned int shift;
 	const unsigned char *seq = s->s3->read_sequence;
 
 	cmp = satsub64be(seq,bitmap->max_seq_num);
 	if (cmp > 0)
 		{
 		memcpy (s->s3->rrec.seq_num,seq,8);
 		return 1; /* this record in new */
 		}
 	shift = -cmp;
 	if (shift >= sizeof(bitmap->map)*8)
 		return 0; /* stale, outside the window */
 	else if (bitmap->map & (1UL<s3->rrec.seq_num,seq,8);
 	return 1;
 	}
 
 
 static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
 	{
 	int cmp;
 	unsigned int shift;
 	const unsigned char *seq = s->s3->read_sequence;
 
 	cmp = satsub64be(seq,bitmap->max_seq_num);
 	if (cmp > 0)
 		{
 		shift = cmp;
 		if (shift < sizeof(bitmap->map)*8)
 			bitmap->map <<= shift, bitmap->map |= 1UL;
 		else
 			bitmap->map = 1UL;
 		memcpy(bitmap->max_seq_num,seq,8);
 		}
 	else	{
 		shift = -cmp;
 		if (shift < sizeof(bitmap->map)*8)
 			bitmap->map |= 1UL<s3->alert_dispatch=0;
 
 	memset(buf, 0x00, sizeof(buf));
 	*ptr++ = s->s3->send_alert[0];
 	*ptr++ = s->s3->send_alert[1];
 
 #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 	if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
 		{	
 		s2n(s->d1->handshake_read_seq, ptr);
 #if 0
 		if ( s->d1->r_msg_hdr.frag_off == 0)  /* waiting for a new msg */
 
 		else
 			s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */
 #endif
 
 #if 0
 		fprintf(stderr, "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",s->d1->handshake_read_seq,s->d1->r_msg_hdr.seq);
 #endif
 		l2n3(s->d1->r_msg_hdr.frag_off, ptr);
 		}
 #endif
 
 	i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
 	if (i <= 0)
 		{
 		s->s3->alert_dispatch=1;
 		/* fprintf( stderr, "not done with alert\n" ); */
 		}
 	else
 		{
 		if (s->s3->send_alert[0] == SSL3_AL_FATAL
 #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 		    || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 #endif
 		    )
 			(void)BIO_flush(s->wbio);
 
 		if (s->msg_callback)
 			s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 
 				2, s, s->msg_callback_arg);
 
 		if (s->info_callback != NULL)
 			cb=s->info_callback;
 		else if (s->ctx->info_callback != NULL)
 			cb=s->ctx->info_callback;
 
 		if (cb != NULL)
 			{
 			j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1];
 			cb(s,SSL_CB_WRITE_ALERT,j);
 			}
 		}
 	return(i);
 	}
 
 
 static DTLS1_BITMAP *
 dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch)
     {
     
     *is_next_epoch = 0;
 
     /* In current epoch, accept HM, CCS, DATA, & ALERT */
     if (rr->epoch == s->d1->r_epoch)
         return &s->d1->bitmap;
 
     /* Only HM and ALERT messages can be from the next epoch */
     else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
         (rr->type == SSL3_RT_HANDSHAKE ||
             rr->type == SSL3_RT_ALERT))
         {
         *is_next_epoch = 1;
         return &s->d1->next_bitmap;
         }
 
     return NULL;
     }
 
 #if 0
 static int
 dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, unsigned short *priority,
 	unsigned long *offset)
 	{
 
 	/* alerts are passed up immediately */
 	if ( rr->type == SSL3_RT_APPLICATION_DATA ||
 		rr->type == SSL3_RT_ALERT)
 		return 0;
 
 	/* Only need to buffer if a handshake is underway.
 	 * (this implies that Hello Request and Client Hello are passed up
 	 * immediately) */
 	if ( SSL_in_init(s))
 		{
 		unsigned char *data = rr->data;
 		/* need to extract the HM/CCS sequence number here */
 		if ( rr->type == SSL3_RT_HANDSHAKE ||
 			rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
 			{
 			unsigned short seq_num;
 			struct hm_header_st msg_hdr;
 			struct ccs_header_st ccs_hdr;
 
 			if ( rr->type == SSL3_RT_HANDSHAKE)
 				{
 				dtls1_get_message_header(data, &msg_hdr);
 				seq_num = msg_hdr.seq;
 				*offset = msg_hdr.frag_off;
 				}
 			else
 				{
 				dtls1_get_ccs_header(data, &ccs_hdr);
 				seq_num = ccs_hdr.seq;
 				*offset = 0;
 				}
 				
 			/* this is either a record we're waiting for, or a
 			 * retransmit of something we happened to previously 
 			 * receive (higher layers will drop the repeat silently */
 			if ( seq_num < s->d1->handshake_read_seq)
 				return 0;
 			if (rr->type == SSL3_RT_HANDSHAKE && 
 				seq_num == s->d1->handshake_read_seq &&
 				msg_hdr.frag_off < s->d1->r_msg_hdr.frag_off)
 				return 0;
 			else if ( seq_num == s->d1->handshake_read_seq &&
 				(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC ||
 					msg_hdr.frag_off == s->d1->r_msg_hdr.frag_off))
 				return 0;
 			else
 				{
 				*priority = seq_num;
 				return 1;
 				}
 			}
 		else /* unknown record type */
 			return 0;
 		}
 
 	return 0;
 	}
 #endif
 
 void
 dtls1_reset_seq_numbers(SSL *s, int rw)
 	{
 	unsigned char *seq;
 	unsigned int seq_bytes = sizeof(s->s3->read_sequence);
 
 	if ( rw & SSL3_CC_READ)
 		{
 		seq = s->s3->read_sequence;
 		s->d1->r_epoch++;
 		memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
 		memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
 		}
 	else
 		{
 		seq = s->s3->write_sequence;
 		memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
 		s->d1->w_epoch++;
 		}
 
 	memset(seq, 0x00, seq_bytes);
 	}
Index: releng/10.1/crypto/openssl/ssl/s3_cbc.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/s3_cbc.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/s3_cbc.c	(revision 284295)
@@ -1,755 +1,755 @@
 /* ssl/s3_cbc.c */
 /* ====================================================================
  * Copyright (c) 2012 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include "../crypto/constant_time_locl.h"
 #include "ssl_locl.h"
 
 #include 
 #include 
 
 /* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length
  * field. (SHA-384/512 have 128-bit length.) */
 #define MAX_HASH_BIT_COUNT_BYTES 16
 
 /* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
  * Currently SHA-384/512 has a 128-byte block size and that's the largest
  * supported by TLS.) */
 #define MAX_HASH_BLOCK_SIZE 128
 
 /* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
  * record in |rec| by updating |rec->length| in constant time.
  *
  * block_size: the block size of the cipher used to encrypt the record.
  * returns:
  *   0: (in non-constant time) if the record is publicly invalid.
  *   1: if the padding was valid
  *  -1: otherwise. */
 int ssl3_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size)
 	{
 	unsigned padding_length, good;
 	const unsigned overhead = 1 /* padding length byte */ + mac_size;
 
 	/* These lengths are all public so we can test them in non-constant
 	 * time. */
 	if (overhead > rec->length)
 		return 0;
 
 	padding_length = rec->data[rec->length-1];
 	good = constant_time_ge(rec->length, padding_length+overhead);
 	/* SSLv3 requires that the padding is minimal. */
 	good &= constant_time_ge(block_size, padding_length+1);
 	padding_length = good & (padding_length+1);
 	rec->length -= padding_length;
 	rec->type |= padding_length<<8;	/* kludge: pass padding length */
 	return constant_time_select_int(good, 1, -1);
 	}
 
 /* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
  * record in |rec| in constant time and returns 1 if the padding is valid and
  * -1 otherwise. It also removes any explicit IV from the start of the record
  * without leaking any timing about whether there was enough space after the
  * padding was removed.
  *
  * block_size: the block size of the cipher used to encrypt the record.
  * returns:
  *   0: (in non-constant time) if the record is publicly invalid.
  *   1: if the padding was valid
  *  -1: otherwise. */
 int tls1_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size)
 	{
 	unsigned padding_length, good, to_check, i;
 	const unsigned overhead = 1 /* padding length byte */ + mac_size;
 	/* Check if version requires explicit IV */
 	if (s->version >= TLS1_1_VERSION || s->version == DTLS1_BAD_VER)
 		{
 		/* These lengths are all public so we can test them in
 		 * non-constant time.
 		 */
 		if (overhead + block_size > rec->length)
 			return 0;
 		/* We can now safely skip explicit IV */
 		rec->data += block_size;
 		rec->input += block_size;
 		rec->length -= block_size;
 		}
 	else if (overhead > rec->length)
 		return 0;
 
 	padding_length = rec->data[rec->length-1];
 
 	/* NB: if compression is in operation the first packet may not be of
 	 * even length so the padding bug check cannot be performed. This bug
 	 * workaround has been around since SSLeay so hopefully it is either
 	 * fixed now or no buggy implementation supports compression [steve]
 	 */
 	if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand)
 		{
 		/* First packet is even in size, so check */
-		if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) &&
+		if ((CRYPTO_memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0", 8) == 0) &&
 		    !(padding_length & 1))
 			{
 			s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
 			}
 		if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) &&
 		    padding_length > 0)
 			{
 			padding_length--;
 			}
 		}
 
 	if (EVP_CIPHER_flags(s->enc_read_ctx->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
 		{
 		/* padding is already verified */
 		rec->length -= padding_length + 1;
 		return 1;
 		}
 
 	good = constant_time_ge(rec->length, overhead+padding_length);
 	/* The padding consists of a length byte at the end of the record and
 	 * then that many bytes of padding, all with the same value as the
 	 * length byte. Thus, with the length byte included, there are i+1
 	 * bytes of padding.
 	 *
 	 * We can't check just |padding_length+1| bytes because that leaks
 	 * decrypted information. Therefore we always have to check the maximum
 	 * amount of padding possible. (Again, the length of the record is
 	 * public information so we can use it.) */
 	to_check = 255; /* maximum amount of padding. */
 	if (to_check > rec->length-1)
 		to_check = rec->length-1;
 
 	for (i = 0; i < to_check; i++)
 		{
 		unsigned char mask = constant_time_ge_8(padding_length, i);
 		unsigned char b = rec->data[rec->length-1-i];
 		/* The final |padding_length+1| bytes should all have the value
 		 * |padding_length|. Therefore the XOR should be zero. */
 		good &= ~(mask&(padding_length ^ b));
 		}
 
 	/* If any of the final |padding_length+1| bytes had the wrong value,
 	 * one or more of the lower eight bits of |good| will be cleared.
 	 */
 	good = constant_time_eq(0xff, good & 0xff);
 	padding_length = good & (padding_length+1);
 	rec->length -= padding_length;
 	rec->type |= padding_length<<8;	/* kludge: pass padding length */
 
 	return constant_time_select_int(good, 1, -1);
 	}
 
 /* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
  * constant time (independent of the concrete value of rec->length, which may
  * vary within a 256-byte window).
  *
  * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
  * this function.
  *
  * On entry:
  *   rec->orig_len >= md_size
  *   md_size <= EVP_MAX_MD_SIZE
  *
  * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
  * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
  * a single or pair of cache-lines, then the variable memory accesses don't
  * actually affect the timing. CPUs with smaller cache-lines [if any] are
  * not multi-core and are not considered vulnerable to cache-timing attacks.
  */
 #define CBC_MAC_ROTATE_IN_PLACE
 
 void ssl3_cbc_copy_mac(unsigned char* out,
 		       const SSL3_RECORD *rec,
 		       unsigned md_size,unsigned orig_len)
 	{
 #if defined(CBC_MAC_ROTATE_IN_PLACE)
 	unsigned char rotated_mac_buf[64+EVP_MAX_MD_SIZE];
 	unsigned char *rotated_mac;
 #else
 	unsigned char rotated_mac[EVP_MAX_MD_SIZE];
 #endif
 
 	/* mac_end is the index of |rec->data| just after the end of the MAC. */
 	unsigned mac_end = rec->length;
 	unsigned mac_start = mac_end - md_size;
 	/* scan_start contains the number of bytes that we can ignore because
 	 * the MAC's position can only vary by 255 bytes. */
 	unsigned scan_start = 0;
 	unsigned i, j;
 	unsigned div_spoiler;
 	unsigned rotate_offset;
 
 	OPENSSL_assert(orig_len >= md_size);
 	OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
 
 #if defined(CBC_MAC_ROTATE_IN_PLACE)
 	rotated_mac = rotated_mac_buf + ((0-(size_t)rotated_mac_buf)&63);
 #endif
 
 	/* This information is public so it's safe to branch based on it. */
 	if (orig_len > md_size + 255 + 1)
 		scan_start = orig_len - (md_size + 255 + 1);
 	/* div_spoiler contains a multiple of md_size that is used to cause the
 	 * modulo operation to be constant time. Without this, the time varies
 	 * based on the amount of padding when running on Intel chips at least.
 	 *
 	 * The aim of right-shifting md_size is so that the compiler doesn't
 	 * figure out that it can remove div_spoiler as that would require it
 	 * to prove that md_size is always even, which I hope is beyond it. */
 	div_spoiler = md_size >> 1;
 	div_spoiler <<= (sizeof(div_spoiler)-1)*8;
 	rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
 
 	memset(rotated_mac, 0, md_size);
 	for (i = scan_start, j = 0; i < orig_len; i++)
 		{
 		unsigned char mac_started = constant_time_ge_8(i, mac_start);
 		unsigned char mac_ended = constant_time_ge_8(i, mac_end);
 		unsigned char b = rec->data[i];
 		rotated_mac[j++] |= b & mac_started & ~mac_ended;
 		j &= constant_time_lt(j,md_size);
 		}
 
 	/* Now rotate the MAC */
 #if defined(CBC_MAC_ROTATE_IN_PLACE)
 	j = 0;
 	for (i = 0; i < md_size; i++)
 		{
 		/* in case cache-line is 32 bytes, touch second line */
 		((volatile unsigned char *)rotated_mac)[rotate_offset^32];
 		out[j++] = rotated_mac[rotate_offset++];
 		rotate_offset &= constant_time_lt(rotate_offset,md_size);
 		}
 #else
 	memset(out, 0, md_size);
 	rotate_offset = md_size - rotate_offset;
 	rotate_offset &= constant_time_lt(rotate_offset,md_size);
 	for (i = 0; i < md_size; i++)
 		{
 		for (j = 0; j < md_size; j++)
 			out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
 		rotate_offset++;
 		rotate_offset &= constant_time_lt(rotate_offset,md_size);
 		}
 #endif
 	}
 
 /* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
  * little-endian order. The value of p is advanced by four. */
 #define u32toLE(n, p) \
 	(*((p)++)=(unsigned char)(n), \
 	 *((p)++)=(unsigned char)(n>>8), \
 	 *((p)++)=(unsigned char)(n>>16), \
 	 *((p)++)=(unsigned char)(n>>24))
 
 /* These functions serialize the state of a hash and thus perform the standard
  * "final" operation without adding the padding and length that such a function
  * typically does. */
 static void tls1_md5_final_raw(void* ctx, unsigned char *md_out)
 	{
 	MD5_CTX *md5 = ctx;
 	u32toLE(md5->A, md_out);
 	u32toLE(md5->B, md_out);
 	u32toLE(md5->C, md_out);
 	u32toLE(md5->D, md_out);
 	}
 
 static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out)
 	{
 	SHA_CTX *sha1 = ctx;
 	l2n(sha1->h0, md_out);
 	l2n(sha1->h1, md_out);
 	l2n(sha1->h2, md_out);
 	l2n(sha1->h3, md_out);
 	l2n(sha1->h4, md_out);
 	}
 #define LARGEST_DIGEST_CTX SHA_CTX
 
 #ifndef OPENSSL_NO_SHA256
 static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out)
 	{
 	SHA256_CTX *sha256 = ctx;
 	unsigned i;
 
 	for (i = 0; i < 8; i++)
 		{
 		l2n(sha256->h[i], md_out);
 		}
 	}
 #undef  LARGEST_DIGEST_CTX
 #define LARGEST_DIGEST_CTX SHA256_CTX
 #endif
 
 #ifndef OPENSSL_NO_SHA512
 static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out)
 	{
 	SHA512_CTX *sha512 = ctx;
 	unsigned i;
 
 	for (i = 0; i < 8; i++)
 		{
 		l2n8(sha512->h[i], md_out);
 		}
 	}
 #undef  LARGEST_DIGEST_CTX
 #define LARGEST_DIGEST_CTX SHA512_CTX
 #endif
 
 /* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
  * which ssl3_cbc_digest_record supports. */
 char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
 	{
 #ifdef OPENSSL_FIPS
 	if (FIPS_mode())
 		return 0;
 #endif
 	switch (EVP_MD_CTX_type(ctx))
 		{
 		case NID_md5:
 		case NID_sha1:
 #ifndef OPENSSL_NO_SHA256
 		case NID_sha224:
 		case NID_sha256:
 #endif
 #ifndef OPENSSL_NO_SHA512
 		case NID_sha384:
 		case NID_sha512:
 #endif
 			return 1;
 		default:
 			return 0;
 		}
 	}
 
 /* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
  * record.
  *
  *   ctx: the EVP_MD_CTX from which we take the hash function.
  *     ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX.
  *   md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
  *   md_out_size: if non-NULL, the number of output bytes is written here.
  *   header: the 13-byte, TLS record header.
  *   data: the record data itself, less any preceeding explicit IV.
  *   data_plus_mac_size: the secret, reported length of the data and MAC
  *     once the padding has been removed.
  *   data_plus_mac_plus_padding_size: the public length of the whole
  *     record, including padding.
  *   is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
  *
  * On entry: by virtue of having been through one of the remove_padding
  * functions, above, we know that data_plus_mac_size is large enough to contain
  * a padding byte and MAC. (If the padding was invalid, it might contain the
  * padding too. ) */
 void ssl3_cbc_digest_record(
 	const EVP_MD_CTX *ctx,
 	unsigned char* md_out,
 	size_t* md_out_size,
 	const unsigned char header[13],
 	const unsigned char *data,
 	size_t data_plus_mac_size,
 	size_t data_plus_mac_plus_padding_size,
 	const unsigned char *mac_secret,
 	unsigned mac_secret_length,
 	char is_sslv3)
 	{
 	union {	double align;
 		unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; } md_state;
 	void (*md_final_raw)(void *ctx, unsigned char *md_out);
 	void (*md_transform)(void *ctx, const unsigned char *block);
 	unsigned md_size, md_block_size = 64;
 	unsigned sslv3_pad_length = 40, header_length, variance_blocks,
 		 len, max_mac_bytes, num_blocks,
 		 num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
 	unsigned int bits;	/* at most 18 bits */
 	unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
 	/* hmac_pad is the masked HMAC key. */
 	unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
 	unsigned char first_block[MAX_HASH_BLOCK_SIZE];
 	unsigned char mac_out[EVP_MAX_MD_SIZE];
 	unsigned i, j, md_out_size_u;
 	EVP_MD_CTX md_ctx;
 	/* mdLengthSize is the number of bytes in the length field that terminates
 	* the hash. */
 	unsigned md_length_size = 8;
 	char length_is_big_endian = 1;
 
 	/* This is a, hopefully redundant, check that allows us to forget about
 	 * many possible overflows later in this function. */
 	OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024);
 
 	switch (EVP_MD_CTX_type(ctx))
 		{
 		case NID_md5:
 			MD5_Init((MD5_CTX*)md_state.c);
 			md_final_raw = tls1_md5_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform;
 			md_size = 16;
 			sslv3_pad_length = 48;
 			length_is_big_endian = 0;
 			break;
 		case NID_sha1:
 			SHA1_Init((SHA_CTX*)md_state.c);
 			md_final_raw = tls1_sha1_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform;
 			md_size = 20;
 			break;
 #ifndef OPENSSL_NO_SHA256
 		case NID_sha224:
 			SHA224_Init((SHA256_CTX*)md_state.c);
 			md_final_raw = tls1_sha256_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
 			md_size = 224/8;
 			break;
 		case NID_sha256:
 			SHA256_Init((SHA256_CTX*)md_state.c);
 			md_final_raw = tls1_sha256_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
 			md_size = 32;
 			break;
 #endif
 #ifndef OPENSSL_NO_SHA512
 		case NID_sha384:
 			SHA384_Init((SHA512_CTX*)md_state.c);
 			md_final_raw = tls1_sha512_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
 			md_size = 384/8;
 			md_block_size = 128;
 			md_length_size = 16;
 			break;
 		case NID_sha512:
 			SHA512_Init((SHA512_CTX*)md_state.c);
 			md_final_raw = tls1_sha512_final_raw;
 			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
 			md_size = 64;
 			md_block_size = 128;
 			md_length_size = 16;
 			break;
 #endif
 		default:
 			/* ssl3_cbc_record_digest_supported should have been
 			 * called first to check that the hash function is
 			 * supported. */
 			OPENSSL_assert(0);
 			if (md_out_size)
 				*md_out_size = -1;
 			return;
 		}
 
 	OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
 	OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
 	OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
 
 	header_length = 13;
 	if (is_sslv3)
 		{
 		header_length =
 			mac_secret_length +
 			sslv3_pad_length +
 			8 /* sequence number */ +
 			1 /* record type */ +
 			2 /* record length */;
 		}
 
 	/* variance_blocks is the number of blocks of the hash that we have to
 	 * calculate in constant time because they could be altered by the
 	 * padding value.
 	 *
 	 * In SSLv3, the padding must be minimal so the end of the plaintext
 	 * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
 	 * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
 	 * termination (0x80 + 64-bit length) don't fit in the final block, we
 	 * say that the final two blocks can vary based on the padding.
 	 *
 	 * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
 	 * required to be minimal. Therefore we say that the final six blocks
 	 * can vary based on the padding.
 	 *
 	 * Later in the function, if the message is short and there obviously
 	 * cannot be this many blocks then variance_blocks can be reduced. */
 	variance_blocks = is_sslv3 ? 2 : 6;
 	/* From now on we're dealing with the MAC, which conceptually has 13
 	 * bytes of `header' before the start of the data (TLS) or 71/75 bytes
 	 * (SSLv3) */
 	len = data_plus_mac_plus_padding_size + header_length;
 	/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
 	* |header|, assuming that there's no padding. */
 	max_mac_bytes = len - md_size - 1;
 	/* num_blocks is the maximum number of hash blocks. */
 	num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
 	/* In order to calculate the MAC in constant time we have to handle
 	 * the final blocks specially because the padding value could cause the
 	 * end to appear somewhere in the final |variance_blocks| blocks and we
 	 * can't leak where. However, |num_starting_blocks| worth of data can
 	 * be hashed right away because no padding value can affect whether
 	 * they are plaintext. */
 	num_starting_blocks = 0;
 	/* k is the starting byte offset into the conceptual header||data where
 	 * we start processing. */
 	k = 0;
 	/* mac_end_offset is the index just past the end of the data to be
 	 * MACed. */
 	mac_end_offset = data_plus_mac_size + header_length - md_size;
 	/* c is the index of the 0x80 byte in the final hash block that
 	 * contains application data. */
 	c = mac_end_offset % md_block_size;
 	/* index_a is the hash block number that contains the 0x80 terminating
 	 * value. */
 	index_a = mac_end_offset / md_block_size;
 	/* index_b is the hash block number that contains the 64-bit hash
 	 * length, in bits. */
 	index_b = (mac_end_offset + md_length_size) / md_block_size;
 	/* bits is the hash-length in bits. It includes the additional hash
 	 * block for the masked HMAC key, or whole of |header| in the case of
 	 * SSLv3. */
 
 	/* For SSLv3, if we're going to have any starting blocks then we need
 	 * at least two because the header is larger than a single block. */
 	if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0))
 		{
 		num_starting_blocks = num_blocks - variance_blocks;
 		k = md_block_size*num_starting_blocks;
 		}
 
 	bits = 8*mac_end_offset;
 	if (!is_sslv3)
 		{
 		/* Compute the initial HMAC block. For SSLv3, the padding and
 		 * secret bytes are included in |header| because they take more
 		 * than a single block. */
 		bits += 8*md_block_size;
 		memset(hmac_pad, 0, md_block_size);
 		OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad));
 		memcpy(hmac_pad, mac_secret, mac_secret_length);
 		for (i = 0; i < md_block_size; i++)
 			hmac_pad[i] ^= 0x36;
 
 		md_transform(md_state.c, hmac_pad);
 		}
 
 	if (length_is_big_endian)
 		{
 		memset(length_bytes,0,md_length_size-4);
 		length_bytes[md_length_size-4] = (unsigned char)(bits>>24);
 		length_bytes[md_length_size-3] = (unsigned char)(bits>>16);
 		length_bytes[md_length_size-2] = (unsigned char)(bits>>8);
 		length_bytes[md_length_size-1] = (unsigned char)bits;
 		}
 	else
 		{
 		memset(length_bytes,0,md_length_size);
 		length_bytes[md_length_size-5] = (unsigned char)(bits>>24);
 		length_bytes[md_length_size-6] = (unsigned char)(bits>>16);
 		length_bytes[md_length_size-7] = (unsigned char)(bits>>8);
 		length_bytes[md_length_size-8] = (unsigned char)bits;
 		}
 
 	if (k > 0)
 		{
 		if (is_sslv3)
 			{
 			/* The SSLv3 header is larger than a single block.
 			 * overhang is the number of bytes beyond a single
 			 * block that the header consumes: either 7 bytes
 			 * (SHA1) or 11 bytes (MD5). */
 			unsigned overhang = header_length-md_block_size;
 			md_transform(md_state.c, header);
 			memcpy(first_block, header + md_block_size, overhang);
 			memcpy(first_block + overhang, data, md_block_size-overhang);
 			md_transform(md_state.c, first_block);
 			for (i = 1; i < k/md_block_size - 1; i++)
 				md_transform(md_state.c, data + md_block_size*i - overhang);
 			}
 		else
 			{
 			/* k is a multiple of md_block_size. */
 			memcpy(first_block, header, 13);
 			memcpy(first_block+13, data, md_block_size-13);
 			md_transform(md_state.c, first_block);
 			for (i = 1; i < k/md_block_size; i++)
 				md_transform(md_state.c, data + md_block_size*i - 13);
 			}
 		}
 
 	memset(mac_out, 0, sizeof(mac_out));
 
 	/* We now process the final hash blocks. For each block, we construct
 	 * it in constant time. If the |i==index_a| then we'll include the 0x80
 	 * bytes and zero pad etc. For each block we selectively copy it, in
 	 * constant time, to |mac_out|. */
 	for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++)
 		{
 		unsigned char block[MAX_HASH_BLOCK_SIZE];
 		unsigned char is_block_a = constant_time_eq_8(i, index_a);
 		unsigned char is_block_b = constant_time_eq_8(i, index_b);
 		for (j = 0; j < md_block_size; j++)
 			{
 			unsigned char b = 0, is_past_c, is_past_cp1;
 			if (k < header_length)
 				b = header[k];
 			else if (k < data_plus_mac_plus_padding_size + header_length)
 				b = data[k-header_length];
 			k++;
 
 			is_past_c = is_block_a & constant_time_ge_8(j, c);
 			is_past_cp1 = is_block_a & constant_time_ge_8(j, c+1);
 			/* If this is the block containing the end of the
 			 * application data, and we are at the offset for the
 			 * 0x80 value, then overwrite b with 0x80. */
                         b =  constant_time_select_8(is_past_c, 0x80, b);
 			/* If this the the block containing the end of the
 			 * application data and we're past the 0x80 value then
 			 * just write zero. */
 			b = b&~is_past_cp1;
 			/* If this is index_b (the final block), but not
 			 * index_a (the end of the data), then the 64-bit
 			 * length didn't fit into index_a and we're having to
 			 * add an extra block of zeros. */
 			b &= ~is_block_b | is_block_a;
 
 			/* The final bytes of one of the blocks contains the
 			 * length. */
 			if (j >= md_block_size - md_length_size)
 				{
 				/* If this is index_b, write a length byte. */
 				b = constant_time_select_8(
 					is_block_b, length_bytes[j-(md_block_size-md_length_size)], b);
 				}
 			block[j] = b;
 			}
 
 		md_transform(md_state.c, block);
 		md_final_raw(md_state.c, block);
 		/* If this is index_b, copy the hash value to |mac_out|. */
 		for (j = 0; j < md_size; j++)
 			mac_out[j] |= block[j]&is_block_b;
 		}
 
 	EVP_MD_CTX_init(&md_ctx);
 	EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */);
 	if (is_sslv3)
 		{
 		/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
 		memset(hmac_pad, 0x5c, sslv3_pad_length);
 
 		EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
 		EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
 		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
 		}
 	else
 		{
 		/* Complete the HMAC in the standard manner. */
 		for (i = 0; i < md_block_size; i++)
 			hmac_pad[i] ^= 0x6a;
 
 		EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
 		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
 		}
 	EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
 	if (md_out_size)
 		*md_out_size = md_out_size_u;
 	EVP_MD_CTX_cleanup(&md_ctx);
 	}
 
 #ifdef OPENSSL_FIPS
 
 /* Due to the need to use EVP in FIPS mode we can't reimplement digests but
  * we can ensure the number of blocks processed is equal for all cases
  * by digesting additional data.
  */
 
 void tls_fips_digest_extra(
 	const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx,
 	const unsigned char *data, size_t data_len, size_t orig_len)
 	{
 	size_t block_size, digest_pad, blocks_data, blocks_orig;
 	if (EVP_CIPHER_CTX_mode(cipher_ctx) != EVP_CIPH_CBC_MODE)
 		return;
 	block_size = EVP_MD_CTX_block_size(mac_ctx);
 	/* We are in FIPS mode if we get this far so we know we have only SHA*
 	 * digests and TLS to deal with.
 	 * Minimum digest padding length is 17 for SHA384/SHA512 and 9
 	 * otherwise.
 	 * Additional header is 13 bytes. To get the number of digest blocks
 	 * processed round up the amount of data plus padding to the nearest
 	 * block length. Block length is 128 for SHA384/SHA512 and 64 otherwise.
 	 * So we have:
 	 * blocks = (payload_len + digest_pad + 13 + block_size - 1)/block_size
 	 * equivalently:
 	 * blocks = (payload_len + digest_pad + 12)/block_size + 1
 	 * HMAC adds a constant overhead.
 	 * We're ultimately only interested in differences so this becomes
 	 * blocks = (payload_len + 29)/128
 	 * for SHA384/SHA512 and
 	 * blocks = (payload_len + 21)/64
 	 * otherwise.
 	 */
 	digest_pad = block_size == 64 ? 21 : 29;
 	blocks_orig = (orig_len + digest_pad)/block_size;
 	blocks_data = (data_len + digest_pad)/block_size;
 	/* MAC enough blocks to make up the difference between the original
 	 * and actual lengths plus one extra block to ensure this is never a
 	 * no op. The "data" pointer should always have enough space to
 	 * perform this operation as it is large enough for a maximum
 	 * length TLS buffer. 
 	 */
 	EVP_DigestSignUpdate(mac_ctx, data,
 				(blocks_orig - blocks_data + 1) * block_size);
 	}
 #endif
Index: releng/10.1/crypto/openssl/ssl/s3_clnt.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/s3_clnt.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/s3_clnt.c	(revision 284295)
@@ -1,3496 +1,3575 @@
 /* ssl/s3_clnt.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 /* ====================================================================
  * Copyright 2005 Nokia. All rights reserved.
  *
  * The portions of the attached software ("Contribution") is developed by
  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
  * license.
  *
  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
  * support (see RFC 4279) to OpenSSL.
  *
  * No patent licenses or other rights except those expressly stated in
  * the OpenSSL open source license shall be deemed granted or received
  * expressly, by implication, estoppel, or otherwise.
  *
  * No assurances are provided by Nokia that the Contribution does not
  * infringe the patent or other intellectual property rights of any third
  * party or that the license provides you with all the necessary rights
  * to make use of the Contribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifdef OPENSSL_FIPS
 #include 
 #endif
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 
 #ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_client_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_client_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
 			ssl_undefined_function,
 			ssl3_connect,
 			ssl3_get_client_method)
 #endif
 
 int ssl3_connect(SSL *s)
 	{
 	BUF_MEM *buf=NULL;
 	unsigned long Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 	
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	/* If we're awaiting a HeartbeatResponse, pretend we
 	 * already got and don't await it anymore, because
 	 * Heartbeats don't make sense during handshakes anyway.
 	 */
 	if (s->tlsext_hb_pending)
 		{
 		s->tlsext_hb_pending = 0;
 		s->tlsext_hb_seq++;
 		}
 #endif
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch(s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->renegotiate=1;
 			s->state=SSL_ST_CONNECT;
 			s->ctx->stats.sess_connect_renegotiate++;
 			/* break */
 		case SSL_ST_BEFORE:
 		case SSL_ST_CONNECT:
 		case SSL_ST_BEFORE|SSL_ST_CONNECT:
 		case SSL_ST_OK|SSL_ST_CONNECT:
 
 			s->server=0;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version & 0xff00 ) != 0x0300)
 				{
 				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
 				ret = -1;
 				goto end;
 				}
 				
 			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_CONNECT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				buf=NULL;
 				}
 
 			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
 
 			/* setup buffing BIO */
 			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
 
 			/* don't push the buffering BIO quite yet */
 
 			ssl3_init_finished_mac(s);
 
 			s->state=SSL3_ST_CW_CLNT_HELLO_A;
 			s->ctx->stats.sess_connect++;
 			s->init_num=0;
 			s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
 			/* Should have been reset by ssl3_get_finished, too. */
 			s->s3->change_cipher_spec = 0;
 			break;
 
 		case SSL3_ST_CW_CLNT_HELLO_A:
 		case SSL3_ST_CW_CLNT_HELLO_B:
 
 			s->shutdown=0;
 			ret=ssl3_client_hello(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_HELLO_A;
 			s->init_num=0;
 
 			/* turn on buffering for the next lot of output */
 			if (s->bbio != s->wbio)
 				s->wbio=BIO_push(s->bbio,s->wbio);
 
 			break;
 
 		case SSL3_ST_CR_SRVR_HELLO_A:
 		case SSL3_ST_CR_SRVR_HELLO_B:
 			ret=ssl3_get_server_hello(s);
 			if (ret <= 0) goto end;
 
 			if (s->hit)
 				{
 				s->state=SSL3_ST_CR_FINISHED_A;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_ticket_expected)
 					{
 					/* receive renewed session ticket */
 					s->state=SSL3_ST_CR_SESSION_TICKET_A;
 					}
 #endif
 				}
 			else
 				s->state=SSL3_ST_CR_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_CERT_A:
 		case SSL3_ST_CR_CERT_B:
 			/* Check if it is anon DH/ECDH, SRP auth */
 			/* or PSK */
 			if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) &&
 			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
 				{
 				ret=ssl3_get_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_CR_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_KEY_EXCH_A:
 		case SSL3_ST_CR_KEY_EXCH_B:
 			ret=ssl3_get_key_exchange(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_CERT_REQ_A;
 			s->init_num=0;
 
 			/* at this point we check that we have the
 			 * required stuff from the server */
 			if (!ssl3_check_cert_and_algorithm(s))
 				{
 				ret= -1;
 				goto end;
 				}
 			break;
 
 		case SSL3_ST_CR_CERT_REQ_A:
 		case SSL3_ST_CR_CERT_REQ_B:
 			ret=ssl3_get_certificate_request(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_DONE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_SRVR_DONE_A:
 		case SSL3_ST_CR_SRVR_DONE_B:
 			ret=ssl3_get_server_done(s);
 			if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_SRP
 			if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP)
 				{
 				if ((ret = SRP_Calc_A_param(s))<=0)
 					{
 					SSLerr(SSL_F_SSL3_CONNECT,SSL_R_SRP_A_CALC);
 					ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
 					goto end;
 					}
 				}
 #endif
 			if (s->s3->tmp.cert_req)
 				s->state=SSL3_ST_CW_CERT_A;
 			else
 				s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 
 			break;
 
 		case SSL3_ST_CW_CERT_A:
 		case SSL3_ST_CW_CERT_B:
 		case SSL3_ST_CW_CERT_C:
 		case SSL3_ST_CW_CERT_D:
 			ret=ssl3_send_client_certificate(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_KEY_EXCH_A:
 		case SSL3_ST_CW_KEY_EXCH_B:
 			ret=ssl3_send_client_key_exchange(s);
 			if (ret <= 0) goto end;
 			/* EAY EAY EAY need to check for DH fix cert
 			 * sent back */
 			/* For TLS, cert_req is set to 2, so a cert chain
 			 * of nothing is sent, but no verify packet is sent */
 			/* XXX: For now, we do not support client 
 			 * authentication in ECDH cipher suites with
 			 * ECDH (rather than ECDSA) certificates.
 			 * We need to skip the certificate verify 
 			 * message when client's ECDH public key is sent 
 			 * inside the client certificate.
 			 */
 			if (s->s3->tmp.cert_req == 1)
 				{
 				s->state=SSL3_ST_CW_CERT_VRFY_A;
 				}
 			else
 				{
 				s->state=SSL3_ST_CW_CHANGE_A;
 				}
 			if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
 				{
 				s->state=SSL3_ST_CW_CHANGE_A;
 				}
 
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CERT_VRFY_A:
 		case SSL3_ST_CW_CERT_VRFY_B:
 			ret=ssl3_send_client_verify(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CHANGE_A:
 		case SSL3_ST_CW_CHANGE_B:
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
 
 #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
 			s->state=SSL3_ST_CW_FINISHED_A;
 #else
 			if (s->s3->next_proto_neg_seen)
 				s->state=SSL3_ST_CW_NEXT_PROTO_A;
 			else
 				s->state=SSL3_ST_CW_FINISHED_A;
 #endif
 			s->init_num=0;
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 #ifdef OPENSSL_NO_COMP
 			s->session->compress_meth=0;
 #else
 			if (s->s3->tmp.new_compression == NULL)
 				s->session->compress_meth=0;
 			else
 				s->session->compress_meth=
 					s->s3->tmp.new_compression->id;
 #endif
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
 		case SSL3_ST_CW_NEXT_PROTO_A:
 		case SSL3_ST_CW_NEXT_PROTO_B:
 			ret=ssl3_send_next_proto(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_FINISHED_A;
 			break;
 #endif
 
 		case SSL3_ST_CW_FINISHED_A:
 		case SSL3_ST_CW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
 				s->method->ssl3_enc->client_finished_label,
 				s->method->ssl3_enc->client_finished_label_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_FLUSH;
 
 			/* clear flags */
 			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
 			if (s->hit)
 				{
 				s->s3->tmp.next_state=SSL_ST_OK;
 				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
 					{
 					s->state=SSL_ST_OK;
 					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
 					s->s3->delay_buf_pop_ret=0;
 					}
 				}
 			else
 				{
 #ifndef OPENSSL_NO_TLSEXT
 				/* Allow NewSessionTicket if ticket expected */
 				if (s->tlsext_ticket_expected)
 					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
 				else
 #endif
 				
 				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
 				}
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_CR_SESSION_TICKET_A:
 		case SSL3_ST_CR_SESSION_TICKET_B:
 			ret=ssl3_get_new_session_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_FINISHED_A;
 			s->init_num=0;
 		break;
 
 		case SSL3_ST_CR_CERT_STATUS_A:
 		case SSL3_ST_CR_CERT_STATUS_B:
 			ret=ssl3_get_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 			s->init_num=0;
 		break;
 #endif
 
 		case SSL3_ST_CR_FINISHED_A:
 		case SSL3_ST_CR_FINISHED_B:
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
 				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
 
 			if (s->hit)
 				s->state=SSL3_ST_CW_CHANGE_A;
 			else
 				s->state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_FLUSH:
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			if (s->init_buf != NULL)
 				{
 				BUF_MEM_free(s->init_buf);
 				s->init_buf=NULL;
 				}
 
 			/* If we are not 'joining' the last two packets,
 			 * remove the buffering now */
 			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
 				ssl_free_wbio_buffer(s);
 			/* else do it later in ssl3_write */
 
 			s->init_num=0;
 			s->renegotiate=0;
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
 			if (s->hit) s->ctx->stats.sess_hit++;
 
 			ret=1;
 			/* s->server=0; */
 			s->handshake_func=ssl3_connect;
 			s->ctx->stats.sess_connect_good++;
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 
 			goto end;
 			/* break; */
 			
 		default:
 			SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 
 		/* did we do anything */
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_CONNECT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	s->in_handshake--;
 	if (buf != NULL)
 		BUF_MEM_free(buf);
 	if (cb != NULL)
 		cb(s,SSL_CB_CONNECT_EXIT,ret);
 	return(ret);
 	}
 
 
 int ssl3_client_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i;
 	unsigned long l;
 #ifndef OPENSSL_NO_COMP
 	int j;
 	SSL_COMP *comp;
 #endif
 
 	buf=(unsigned char *)s->init_buf->data;
 	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
 		{
 		SSL_SESSION *sess = s->session;
 		if ((sess == NULL) ||
 			(sess->ssl_version != s->version) ||
 			!sess->session_id_length ||
 			(sess->not_resumable))
 			{
 			if (!ssl_get_new_session(s,0))
 				goto err;
 			}
 		/* else use the pre-loaded session */
 
 		p=s->s3->client_random;
 
 		if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
 			goto err;
 
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		/* version indicates the negotiated version: for example from
 		 * an SSLv2/v3 compatible client hello). The client_version
 		 * field is the maximum version we permit and it is also
 		 * used in RSA encrypted premaster secrets. Some servers can
 		 * choke if we initially report a higher version then
 		 * renegotiate to a lower one in the premaster secret. This
 		 * didn't happen with TLS 1.0 as most servers supported it
 		 * but it can with TLS 1.1 or later if the server only supports
 		 * 1.0.
 		 *
 		 * Possible scenario with previous logic:
 		 * 	1. Client hello indicates TLS 1.2
 		 * 	2. Server hello says TLS 1.0
 		 *	3. RSA encrypted premaster secret uses 1.2.
 		 * 	4. Handhaked proceeds using TLS 1.0.
 		 *	5. Server sends hello request to renegotiate.
 		 *	6. Client hello indicates TLS v1.0 as we now
 		 *	   know that is maximum server supports.
 		 *	7. Server chokes on RSA encrypted premaster secret
 		 *	   containing version 1.0.
 		 *
 		 * For interoperability it should be OK to always use the
 		 * maximum version we support in client hello and then rely
 		 * on the checking of version to ensure the servers isn't
 		 * being inconsistent: for example initially negotiating with
 		 * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
 		 * client_version in client hello and not resetting it to
 		 * the negotiated version.
 		 */
 #if 0
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 		s->client_version=s->version;
 #else
 		*(p++)=s->client_version>>8;
 		*(p++)=s->client_version&0xff;
 #endif
 
 		/* Random stuff */
 		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* Session ID */
 		if (s->new_session)
 			i=0;
 		else
 			i=s->session->session_id_length;
 		*(p++)=i;
 		if (i != 0)
 			{
 			if (i > (int)sizeof(s->session->session_id))
 				{
 				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			memcpy(p,s->session->session_id,i);
 			p+=i;
 			}
 		
 		/* Ciphers supported */
 		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
 			goto err;
 			}
 #ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
 			/* Some servers hang if client hello > 256 bytes
 			 * as hack workaround chop number of supported ciphers
 			 * to keep it well below this if we use TLS v1.2
 			 */
 			if (TLS1_get_version(s) >= TLS1_2_VERSION
 				&& i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
 				i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
 #endif
 		s2n(i,p);
 		p+=i;
 
 		/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 		*(p++)=1;
 #else
 
 		if ((s->options & SSL_OP_NO_COMPRESSION)
 					|| !s->ctx->comp_methods)
 			j=0;
 		else
 			j=sk_SSL_COMP_num(s->ctx->comp_methods);
 		*(p++)=1+j;
 		for (i=0; ictx->comp_methods,i);
 			*(p++)=comp->id;
 			}
 #endif
 		*(p++)=0; /* Add the NULL method */
 
 #ifndef OPENSSL_NO_TLSEXT
 		/* TLS extensions*/
 		if (ssl_prepare_clienthello_tlsext(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 			}
 		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 #endif
 		
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_CLIENT_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_CW_CLNT_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_CLNT_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_server_hello(SSL *s)
 	{
 	STACK_OF(SSL_CIPHER) *sk;
 	const SSL_CIPHER *c;
 	unsigned char *p,*d;
 	int i,al,ok;
 	unsigned int j;
 	long n;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp;
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_HELLO_A,
 		SSL3_ST_CR_SRVR_HELLO_B,
 		-1,
 		20000, /* ?? */
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
 		{
 		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
 			{
 			if ( s->d1->send_cookie == 0)
 				{
 				s->s3->tmp.reuse_message = 1;
 				return 1;
 				}
 			else /* already sent a cookie */
 				{
 				al=SSL_AD_UNEXPECTED_MESSAGE;
 				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 				goto f_err;
 				}
 			}
 		}
 	
 	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 
 	d=p=(unsigned char *)s->init_msg;
 
 	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
 		s->version=(s->version&0xff00)|p[1];
 		al=SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 	p+=2;
 
 	/* load the server hello data */
 	/* load the server random */
 	memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	s->hit = 0;
 
 	/* get the session-id */
 	j= *(p++);
 
 	if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG);
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* check if we want to resume the session based on external pre-shared secret */
 	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
 		{
 		SSL_CIPHER *pref_cipher=NULL;
 		s->session->master_key_length=sizeof(s->session->master_key);
 		if (s->tls_session_secret_cb(s, s->session->master_key,
 					     &s->session->master_key_length,
 					     NULL, &pref_cipher,
 					     s->tls_session_secret_cb_arg))
 			{
 			s->session->cipher = pref_cipher ?
 				pref_cipher : ssl_get_cipher_by_char(s, p+j);
 			s->hit = 1;
 			}
 		}
 #endif /* OPENSSL_NO_TLSEXT */
 
 	if (!s->hit && j != 0 && j == s->session->session_id_length
 	    && memcmp(p,s->session->session_id,j) == 0)
 	    {
 	    if(s->sid_ctx_length != s->session->sid_ctx_length
 	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length))
 		{
 		/* actually a client application bug */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 		goto f_err;
 		}
 	    s->hit=1;
 	    }
 	/* a miss or crap from the other end */
 	if (!s->hit)
 		{
 		/* If we were trying for session-id reuse, make a new
 		 * SSL_SESSION so we don't stuff up other people */
 		if (s->session->session_id_length > 0)
 			{
 			if (!ssl_get_new_session(s,0))
 				{
 				al=SSL_AD_INTERNAL_ERROR;
 				goto f_err;
 				}
 			}
 		s->session->session_id_length=j;
 		memcpy(s->session->session_id,p,j); /* j could be 0 */
 		}
 	p+=j;
 	c=ssl_get_cipher_by_char(s,p);
 	if (c == NULL)
 		{
 		/* unknown cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
 		goto f_err;
 		}
 	/* TLS v1.2 only ciphersuites require v1.2 or later */
 	if ((c->algorithm_ssl & SSL_TLSV1_2) && 
 		(TLS1_get_version(s) < TLS1_2_VERSION))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_SRP
 	if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) &&
 		    !(s->srp_ctx.srp_Mask & SSL_kSRP))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
 		goto f_err;
 		}
 #endif /* OPENSSL_NO_SRP */
 	p+=ssl_put_cipher_by_char(s,NULL,NULL);
 
 	sk=ssl_get_ciphers_by_id(s);
 	i=sk_SSL_CIPHER_find(sk,c);
 	if (i < 0)
 		{
 		/* we did not say we would use this cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
 		goto f_err;
 		}
 
 	/* Depending on the session caching (internal/external), the cipher
 	   and/or cipher_id values may not be set. Make sure that
 	   cipher_id is set and use it for comparison. */
 	if (s->session->cipher)
 		s->session->cipher_id = s->session->cipher->id;
 	if (s->hit && (s->session->cipher_id != c->id))
 		{
 /* Workaround is now obsolete */
 #if 0
 		if (!(s->options &
 			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
 #endif
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
 			goto f_err;
 			}
 		}
 	s->s3->tmp.new_cipher=c;
 	/* Don't digest cached records if TLS v1.2: we may need them for
 	 * client authentication.
 	 */
 	if (TLS1_get_version(s) < TLS1_2_VERSION && !ssl3_digest_cached_records(s))
 		{
 		al = SSL_AD_INTERNAL_ERROR;
 		goto f_err;
 		}
 	/* lets get the compression algorithm */
 	/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 	if (*(p++) != 0)
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 	/* If compression is disabled we'd better not try to resume a session
 	 * using compression.
 	 */
 	if (s->session->compress_meth != 0)
 		{
 		al=SSL_AD_INTERNAL_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
 		goto f_err;
 		}
 #else
 	j= *(p++);
 	if (s->hit && j != s->session->compress_meth)
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
 		goto f_err;
 		}
 	if (j == 0)
 		comp=NULL;
 	else if (s->options & SSL_OP_NO_COMPRESSION)
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
 		goto f_err;
 		}
 	else
 		comp=ssl3_comp_find(s->ctx->comp_methods,j);
 	
 	if ((j != 0) && (comp == NULL))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 	else
 		{
 		s->s3->tmp.new_compression=comp;
 		}
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_serverhello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err; 
 			}
 		if (ssl_check_serverhello_tlsext(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
 				goto err;
 			}
 		}
 #endif
 
 	if (p != (d+n))
 		{
 		/* wrong packet length */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(-1);
 	}
 
 int ssl3_get_server_certificate(SSL *s)
 	{
 	int al,i,ok,ret= -1;
 	unsigned long n,nc,llen,l;
 	X509 *x=NULL;
 	const unsigned char *q,*p;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 	SESS_CERT *sc;
 	EVP_PKEY *pkey=NULL;
 	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_A,
 		SSL3_ST_CR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
 		((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && 
 		(s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&q,l);
 		if (x == NULL)
 			{
 			al=SSL_AD_BAD_CERTIFICATE;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto f_err;
 			}
 		if (q != (p+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		p=q;
 		}
 
 	i=ssl_verify_cert_chain(s,sk);
 	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
 #ifndef OPENSSL_NO_KRB5
 	    && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
 		 (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
 #endif /* OPENSSL_NO_KRB5 */
 		)
 		{
 		al=ssl_verify_alarm_type(s->verify_result);
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
 		goto f_err; 
 		}
 	ERR_clear_error(); /* but we keep s->verify_result */
 
 	sc=ssl_sess_cert_new();
 	if (sc == NULL) goto err;
 
 	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
 	s->session->sess_cert=sc;
 
 	sc->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does include the peer's
 	 * certificate, which we don't include in s3_srvr.c */
 	x=sk_X509_value(sk,0);
 	sk=NULL;
  	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
 
 	pkey=X509_get_pubkey(x);
 
 	/* VRS: allow null cert if auth == KRB5 */
 	need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
 	            (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
 	            ? 0 : 1;
 
 #ifdef KSSL_DEBUG
 	fprintf(stderr,"pkey,x = %p, %p\n", pkey,x);
 	fprintf(stderr,"ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
 	fprintf(stderr,"cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name,
 		s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert);
 #endif    /* KSSL_DEBUG */
 
 	if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
 		goto f_err;
 		}
 
 	i=ssl_cert_type(x,pkey);
 	if (need_cert && i < 0)
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNKNOWN_CERTIFICATE_TYPE);
 		goto f_err;
 		}
 
 	if (need_cert)
 		{
 		sc->peer_cert_type=i;
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		/* Why would the following ever happen?
 		 * We just created sc a couple of lines ago. */
 		if (sc->peer_pkeys[i].x509 != NULL)
 			X509_free(sc->peer_pkeys[i].x509);
 		sc->peer_pkeys[i].x509=x;
 		sc->peer_key= &(sc->peer_pkeys[i]);
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		s->session->peer=x;
 		}
 	else
 		{
 		sc->peer_cert_type=i;
 		sc->peer_key= NULL;
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		s->session->peer=NULL;
 		}
 	s->session->verify_result = s->verify_result;
 
 	x=NULL;
 	ret=1;
 
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	EVP_PKEY_free(pkey);
 	X509_free(x);
 	sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_get_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
 #endif
 	EVP_MD_CTX md_ctx;
 	unsigned char *param,*p;
 	int al,j,ok;
 	long i,param_len,n,alg_k,alg_a;
 	EVP_PKEY *pkey=NULL;
 	const EVP_MD *md = NULL;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh = NULL;
 	BN_CTX *bn_ctx = NULL;
 	EC_POINT *srvr_ecpoint = NULL;
 	int curve_nid = 0;
 	int encoded_pt_len = 0;
 #endif
 
 	EVP_MD_CTX_init(&md_ctx);
 
 	/* use same message size as in ssl3_get_certificate_request()
 	 * as ServerKeyExchange message may be skipped */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_KEY_EXCH_A,
 		SSL3_ST_CR_KEY_EXCH_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 
 	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 
 	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
 		{
 		/*
 		 * Can't skip server key exchange if this is an ephemeral
 		 * ciphersuite.
 		 */
 		if (alg_k & (SSL_kEDH|SSL_kEECDH))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
 			al = SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 #ifndef OPENSSL_NO_PSK
 		/* In plain PSK ciphersuite, ServerKeyExchange can be
 		   omitted if no identity hint is sent. Set
 		   session->sess_cert anyway to avoid problems
 		   later.*/
 		if (alg_k & SSL_kPSK)
 			{
 			s->session->sess_cert=ssl_sess_cert_new();
 			if (s->ctx->psk_identity_hint)
 				OPENSSL_free(s->ctx->psk_identity_hint);
 			s->ctx->psk_identity_hint = NULL;
 			}
 #endif
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	param=p=(unsigned char *)s->init_msg;
 	if (s->session->sess_cert != NULL)
 		{
 #ifndef OPENSSL_NO_RSA
 		if (s->session->sess_cert->peer_rsa_tmp != NULL)
 			{
 			RSA_free(s->session->sess_cert->peer_rsa_tmp);
 			s->session->sess_cert->peer_rsa_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		if (s->session->sess_cert->peer_dh_tmp)
 			{
 			DH_free(s->session->sess_cert->peer_dh_tmp);
 			s->session->sess_cert->peer_dh_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->session->sess_cert->peer_ecdh_tmp)
 			{
 			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
 			s->session->sess_cert->peer_ecdh_tmp=NULL;
 			}
 #endif
 		}
 	else
 		{
 		s->session->sess_cert=ssl_sess_cert_new();
 		}
 
 	/* Total length of the parameters including the length prefix */
 	param_len=0;
 
 	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
 
 	al=SSL_AD_DECODE_ERROR;
 
 #ifndef OPENSSL_NO_PSK
 	if (alg_k & SSL_kPSK)
 		{
 		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		/* Store PSK identity hint for later use, hint is used
 		 * in ssl3_send_client_key_exchange.  Assume that the
 		 * maximum length of a PSK identity hint can be as
 		 * long as the maximum length of a PSK identity. */
 		if (i > PSK_MAX_IDENTITY_LEN)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto f_err;
 			}
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		/* If received PSK identity hint contains NULL
 		 * characters, the hint is truncated from the first
 		 * NULL. p may not be ending with NULL, so create a
 		 * NULL-terminated string. */
 		memcpy(tmp_id_hint, p, i);
 		memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
 		if (s->ctx->psk_identity_hint != NULL)
 			OPENSSL_free(s->ctx->psk_identity_hint);
 		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
 		if (s->ctx->psk_identity_hint == NULL)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
 			goto f_err;
 			}	   
 
 		p+=i;
 		n-=param_len;
 		}
 	else
 #endif /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
 	if (alg_k & SSL_kSRP)
 		{
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_N_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(s->srp_ctx.N=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_G_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(s->srp_ctx.g=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 
 		if (1 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 1;
 
 		i = (unsigned int)(p[0]);
 		p++;
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_S_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(s->srp_ctx.s=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_B_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(s->srp_ctx.B=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 		if (!srp_verify_server_param(s, &al))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
 			goto f_err;
 			}
 
 /* We must check if there is a certificate */
 #ifndef OPENSSL_NO_RSA
 		if (alg_a & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #else
 		if (0)
 			;
 #endif
 #ifndef OPENSSL_NO_DSA
 		else if (alg_a & SSL_aDSS)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
 #endif
 		}
 	else
 #endif /* !OPENSSL_NO_SRP */
 #ifndef OPENSSL_NO_RSA
 	if (alg_k & SSL_kRSA)
 		{
 		/* Temporary RSA keys only allowed in export ciphersuites */
 		if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher))
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
 		if ((rsa=RSA_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 		/* this should be because we are using an export cipher */
 		if (alg_a & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 		else
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
+
+		if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+			al = SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
+			goto f_err;
+		}
+
 		s->session->sess_cert->peer_rsa_tmp=rsa;
 		rsa=NULL;
 		}
 #else /* OPENSSL_NO_RSA */
 	if (0)
 		;
 #endif
 #ifndef OPENSSL_NO_DH
 	else if (alg_k & SSL_kEDH)
 		{
 		if ((dh=DH_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->p=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->g=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 #ifndef OPENSSL_NO_RSA
 		if (alg_a & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #else
 		if (0)
 			;
 #endif
 #ifndef OPENSSL_NO_DSA
 		else if (alg_a & SSL_aDSS)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
 #endif
 		/* else anonymous DH, so no certificate or pkey. */
 
 		s->session->sess_cert->peer_dh_tmp=dh;
 		dh=NULL;
 		}
 	else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_DH */
 
 #ifndef OPENSSL_NO_ECDH
 	else if (alg_k & SSL_kEECDH)
 		{
 		EC_GROUP *ngroup;
 		const EC_GROUP *group;
 
 		if ((ecdh=EC_KEY_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		/* Extract elliptic curve parameters and the
 		 * server's ephemeral ECDH public key.
 		 * Keep accumulating lengths of various components in
 		 * param_len and make sure it never exceeds n.
 		 */
 
 		/* XXX: For now we only support named (not generic) curves
 		 * and the ECParameters in this case is just three bytes. We
 		 * also need one byte for the length of the encoded point
 		 */
 		param_len=4;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 
 		if ((*p != NAMED_CURVE_TYPE) || 
 		    ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0))
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
 			goto f_err;
 			}
 
 		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
 		if (ngroup == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_KEY_set_group(ecdh, ngroup) == 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		EC_GROUP_free(ngroup);
 
 		group = EC_KEY_get0_group(ecdh);
 
 		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 		    (EC_GROUP_get_degree(group) > 163))
 			{
 			al=SSL_AD_EXPORT_RESTRICTION;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 			goto f_err;
 			}
 
 		p+=3;
 
 		/* Next, get the encoded ECPoint */
 		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
 		    ((bn_ctx = BN_CTX_new()) == NULL))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		encoded_pt_len = *p;  /* length of encoded point */
 		p+=1;
 
 		if ((encoded_pt_len > n - param_len) ||
 		    (EC_POINT_oct2point(group, srvr_ecpoint, 
 			p, encoded_pt_len, bn_ctx) == 0))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
 			goto f_err;
 			}
 		param_len += encoded_pt_len;
 
 		n-=param_len;
 		p+=encoded_pt_len;
 
 		/* The ECC/TLS specification does not mention
 		 * the use of DSA to sign ECParameters in the server
 		 * key exchange message. We do support RSA and ECDSA.
 		 */
 		if (0) ;
 #ifndef OPENSSL_NO_RSA
 		else if (alg_a & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		else if (alg_a & SSL_aECDSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 #endif
 		/* else anonymous ECDH, so no certificate or pkey. */
 		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
 		s->session->sess_cert->peer_ecdh_tmp=ecdh;
 		ecdh=NULL;
 		BN_CTX_free(bn_ctx);
 		bn_ctx = NULL;
 		EC_POINT_free(srvr_ecpoint);
 		srvr_ecpoint = NULL;
 		}
 	else if (alg_k)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_ECDH */
 
 
 	/* p points to the next byte, there are 'n' bytes left */
 
 	/* if it was signed, check the signature */
 	if (pkey != NULL)
 		{
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
 			int sigalg;
 			if (2 > n)
 				{
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 					SSL_R_LENGTH_TOO_SHORT);
 				goto f_err;
 				}
 
 			sigalg = tls12_get_sigid(pkey);
 			/* Should never happen */
 			if (sigalg == -1)
 				{
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			/* Check key type is consistent with signature */
 			if (sigalg != (int)p[1])
 				{
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			md = tls12_get_hash(p[0]);
 			if (md == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
 				goto f_err;
 				}
 #ifdef SSL_DEBUG
 fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
 			p += 2;
 			n -= 2;
 			}
 		else
 			md = EVP_sha1();
 
 		if (2 > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 		n-=2;
 		j=EVP_PKEY_size(pkey);
 
 		/* Check signature length. If n is 0 then signature is empty */
 		if ((i != n) || (n > j) || (n <= 0))
 			{
 			/* wrong packet length */
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
 			goto f_err;
 			}
 
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA && TLS1_get_version(s) < TLS1_2_VERSION)
 			{
 			int num;
 			unsigned int size;
 
 			j=0;
 			q=md_buf;
 			for (num=2; num > 0; num--)
 				{
 				EVP_MD_CTX_set_flags(&md_ctx,
 					EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 				EVP_DigestInit_ex(&md_ctx,(num == 2)
 					?s->ctx->md5:s->ctx->sha1, NULL);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,param,param_len);
 				EVP_DigestFinal_ex(&md_ctx,q,&size);
 				q+=size;
 				j+=size;
 				}
 			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
 								pkey->pkey.rsa);
 			if (i < 0)
 				{
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
 				goto f_err;
 				}
 			if (i == 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 			{
 			EVP_VerifyInit_ex(&md_ctx, md, NULL);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
 			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		}
 	else
 		{
 		/* aNULL, aSRP or kPSK do not need public keys */
 		if (!(alg_a & (SSL_aNULL|SSL_aSRP)) && !(alg_k & SSL_kPSK))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		/* still data left over */
 		if (n != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
 			goto f_err;
 			}
 		}
 	EVP_PKEY_free(pkey);
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	EVP_PKEY_free(pkey);
 #ifndef OPENSSL_NO_RSA
 	if (rsa != NULL)
 		RSA_free(rsa);
 #endif
 #ifndef OPENSSL_NO_DH
 	if (dh != NULL)
 		DH_free(dh);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	EC_POINT_free(srvr_ecpoint);
 	if (ecdh != NULL)
 		EC_KEY_free(ecdh);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_get_certificate_request(SSL *s)
 	{
 	int ok,ret=0;
 	unsigned long n,nc,l;
 	unsigned int llen, ctype_num,i;
 	X509_NAME *xn=NULL;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509_NAME) *ca_sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_REQ_A,
 		SSL3_ST_CR_CERT_REQ_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	s->s3->tmp.cert_req=0;
 
 	if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
 		{
 		s->s3->tmp.reuse_message=1;
 		/* If we get here we don't need any cached handshake records
 		 * as we wont be doing client auth.
 		 */
 		if (s->s3->handshake_buffer)
 			{
 			if (!ssl3_digest_cached_records(s))
 				goto err;
 			}
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
 		goto err;
 		}
 
 	/* TLS does not like anon-DH with client cert */
 	if (s->version > SSL3_VERSION)
 		{
 		if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
 			goto err;
 			}
 		}
 
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* get the certificate types */
 	ctype_num= *(p++);
 	if (ctype_num > SSL3_CT_NUMBER)
 		ctype_num=SSL3_CT_NUMBER;
 	for (i=0; is3->tmp.ctype[i]= p[i];
 	p+=ctype_num;
 	if (TLS1_get_version(s) >= TLS1_2_VERSION)
 		{
 		n2s(p, llen);
 		/* Check we have enough room for signature algorithms and
 		 * following length value.
 		 */
 		if ((unsigned long)(p - d + llen + 2) > n)
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 		if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
 			goto err;
 			}
 		p += llen;
 		}
 
 	/* get the CA RDNs */
 	n2s(p,llen);
 #if 0
 {
 FILE *out;
 out=fopen("/tmp/vsign.der","w");
 fwrite(p,1,llen,out);
 fclose(out);
 }
 #endif
 
 	if ((unsigned long)(p - d + llen) != n)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
 		goto err;
 		}
 
 	for (nc=0; nc llen)
 			{
 			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 				goto cont; /* netscape bugs */
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
 			goto err;
 			}
 
 		q=p;
 
 		if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
 			{
 			/* If netscape tolerance is on, ignore errors */
 			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
 				goto cont;
 			else
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
 				goto err;
 				}
 			}
 
 		if (q != (p+l))
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
 			goto err;
 			}
 		if (!sk_X509_NAME_push(ca_sk,xn))
 			{
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		p+=l;
 		nc+=l+2;
 		}
 
 	if (0)
 		{
 cont:
 		ERR_clear_error();
 		}
 
 	/* we should setup a certificate to return.... */
 	s->s3->tmp.cert_req=1;
 	s->s3->tmp.ctype_num=ctype_num;
 	if (s->s3->tmp.ca_names != NULL)
 		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
 	s->s3->tmp.ca_names=ca_sk;
 	ca_sk=NULL;
 
 	ret=1;
 err:
 	if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
 	return(ret);
 	}
 
 static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
 	{
 	return(X509_NAME_cmp(*a,*b));
 	}
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_get_new_session_ticket(SSL *s)
 	{
 	int ok,al,ret=0, ticklen;
 	long n;
 	const unsigned char *p;
 	unsigned char *d;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SESSION_TICKET_A,
 		SSL3_ST_CR_SESSION_TICKET_B,
 		SSL3_MT_NEWSESSION_TICKET,
 		16384,
 		&ok);
 
 	if (!ok)
 		return((int)n);
 
 	if (n < 6)
 		{
 		/* need at least ticket_lifetime_hint + ticket length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 
-	p=d=(unsigned char *)s->init_msg;
+    p = d = (unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
 	if (ticklen + 6 != n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->session->tlsext_tick)
 		{
 		OPENSSL_free(s->session->tlsext_tick);
 		s->session->tlsext_ticklen = 0;
 		}
 	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
 	if (!s->session->tlsext_tick)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	memcpy(s->session->tlsext_tick, p, ticklen);
 	s->session->tlsext_ticklen = ticklen;
 	/* There are two ways to detect a resumed ticket session.
 	 * One is to set an appropriate session ID and then the server
 	 * must return a match in ServerHello. This allows the normal
 	 * client session ID matching to work and we know much 
 	 * earlier that the ticket has been accepted.
 	 * 
 	 * The other way is to set zero length session ID when the
 	 * ticket is presented and rely on the handshake to determine
 	 * session resumption.
 	 *
 	 * We choose the former approach because this fits in with
 	 * assumptions elsewhere in OpenSSL. The session ID is set
 	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
 	 * ticket.
 	 */ 
 	EVP_Digest(p, ticklen,
 			s->session->session_id, &s->session->session_id_length,
 #ifndef OPENSSL_NO_SHA256
 							EVP_sha256(), NULL);
 #else
 							EVP_sha1(), NULL);
 #endif
 	ret=1;
 	return(ret);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(-1);
 	}
 
 int ssl3_get_cert_status(SSL *s)
 	{
 	int ok, al;
 	unsigned long resplen,n;
 	const unsigned char *p;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_STATUS_A,
 		SSL3_ST_CR_CERT_STATUS_B,
 		SSL3_MT_CERTIFICATE_STATUS,
 		16384,
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n < 4)
 		{
 		/* need at least status type + length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	p = (unsigned char *)s->init_msg;
 	if (*p++ != TLSEXT_STATUSTYPE_ocsp)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
 		goto f_err;
 		}
 	n2l3(p, resplen);
 	if (resplen + 4 != n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->tlsext_ocsp_resp)
 		OPENSSL_free(s->tlsext_ocsp_resp);
 	s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
 	if (!s->tlsext_ocsp_resp)
 		{
 		al = SSL_AD_INTERNAL_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 		goto f_err;
 		}
 	s->tlsext_ocsp_resplen = resplen;
 	if (s->ctx->tlsext_status_cb)
 		{
 		int ret;
 		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 		if (ret == 0)
 			{
 			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
 			goto f_err;
 			}
 		if (ret < 0)
 			{
 			al = SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 			goto f_err;
 			}
 		}
 	return 1;
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 	return(-1);
 	}
 #endif
 
 int ssl3_get_server_done(SSL *s)
 	{
 	int ok,ret=0;
 	long n;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_DONE_A,
 		SSL3_ST_CR_SRVR_DONE_B,
 		SSL3_MT_SERVER_DONE,
 		30, /* should be very small, like 0 :-) */
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n > 0)
 		{
 		/* should contain no data */
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
 		return -1;
 		}
 	ret=1;
 	return(ret);
 	}
 
 
 int ssl3_send_client_key_exchange(SSL *s)
 	{
 	unsigned char *p,*d;
 	int n;
 	unsigned long alg_k;
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_KRB5
 	KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *clnt_ecdh = NULL;
 	const EC_POINT *srvr_ecpoint = NULL;
 	EVP_PKEY *srvr_pub_pkey = NULL;
 	unsigned char *encodedPoint = NULL;
 	int encoded_pt_len = 0;
 	BN_CTX * bn_ctx = NULL;
 #endif
 
 	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 
 		/* Fool emacs indentation */
 		if (0) {}
 #ifndef OPENSSL_NO_RSA
 		else if (alg_k & SSL_kRSA)
 			{
 			RSA *rsa;
 			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 
 			if (s->session->sess_cert == NULL)
 				{
 				/* We should always have a server certificate with SSL_kRSA. */
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if (s->session->sess_cert->peer_rsa_tmp != NULL)
 				rsa=s->session->sess_cert->peer_rsa_tmp;
 			else
 				{
 				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 				if ((pkey == NULL) ||
 					(pkey->type != EVP_PKEY_RSA) ||
 					(pkey->pkey.rsa == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 				rsa=pkey->pkey.rsa;
 				EVP_PKEY_free(pkey);
 				}
 				
 			tmp_buf[0]=s->client_version>>8;
 			tmp_buf[1]=s->client_version&0xff;
 			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 					goto err;
 
 			s->session->master_key_length=sizeof tmp_buf;
 
 			q=p;
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				p+=2;
 			n=RSA_public_encrypt(sizeof tmp_buf,
 				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
 #ifdef PKCS1_CHECK
 			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
 			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
 #endif
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
 				goto err;
 				}
 
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				{
 				s2n(n,q);
 				n+=2;
 				}
 
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf,sizeof tmp_buf);
 			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
 			}
 #endif
 #ifndef OPENSSL_NO_KRB5
 		else if (alg_k & SSL_kKRB5)
 			{
 			krb5_error_code	krb5rc;
 			KSSL_CTX	*kssl_ctx = s->kssl_ctx;
 			/*  krb5_data	krb5_ap_req;  */
 			krb5_data	*enc_ticket;
 			krb5_data	authenticator, *authp = NULL;
 			EVP_CIPHER_CTX	ciph_ctx;
 			const EVP_CIPHER *enc = NULL;
 			unsigned char	iv[EVP_MAX_IV_LENGTH];
 			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
 						+ EVP_MAX_IV_LENGTH];
 			int 		padl, outl = sizeof(epms);
 
 			EVP_CIPHER_CTX_init(&ciph_ctx);
 
 #ifdef KSSL_DEBUG
 			fprintf(stderr,"ssl3_send_client_key_exchange(%lx & %lx)\n",
 				alg_k, SSL_kKRB5);
 #endif	/* KSSL_DEBUG */
 
 			authp = NULL;
 #ifdef KRB5SENDAUTH
 			if (KRB5SENDAUTH)  authp = &authenticator;
 #endif	/* KRB5SENDAUTH */
 
 			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
 				&kssl_err);
 			enc = kssl_map_enc(kssl_ctx->enctype);
 			if (enc == NULL)
 			    goto err;
 #ifdef KSSL_DEBUG
 			{
 			fprintf(stderr,"kssl_cget_tkt rtn %d\n", krb5rc);
 			if (krb5rc && kssl_err.text)
 			  fprintf(stderr,"kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
 			}
 #endif	/* KSSL_DEBUG */
 
 			if (krb5rc)
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,
 						SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 						kssl_err.reason);
 				goto err;
 				}
 
 			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
 			**  in place of RFC 2712 KerberosWrapper, as in:
 			**
 			**  Send ticket (copy to *p, set n = length)
 			**  n = krb5_ap_req.length;
 			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
 			**  if (krb5_ap_req.data)  
 			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
 			**
 			**  Now using real RFC 2712 KerberosWrapper
 			**  (Thanks to Simon Wilkinson )
 			**  Note: 2712 "opaque" types are here replaced
 			**  with a 2-byte length followed by the value.
 			**  Example:
 			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
 			**  Where "xx xx" = length bytes.  Shown here with
 			**  optional authenticator omitted.
 			*/
 
 			/*  KerberosWrapper.Ticket		*/
 			s2n(enc_ticket->length,p);
 			memcpy(p, enc_ticket->data, enc_ticket->length);
 			p+= enc_ticket->length;
 			n = enc_ticket->length + 2;
 
 			/*  KerberosWrapper.Authenticator	*/
 			if (authp  &&  authp->length)  
 				{
 				s2n(authp->length,p);
 				memcpy(p, authp->data, authp->length);
 				p+= authp->length;
 				n+= authp->length + 2;
 				
 				free(authp->data);
 				authp->data = NULL;
 				authp->length = 0;
 				}
 			else
 				{
 				s2n(0,p);/*  null authenticator length	*/
 				n+=2;
 				}
  
 			    tmp_buf[0]=s->client_version>>8;
 			    tmp_buf[1]=s->client_version&0xff;
 			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 				goto err;
 
 			/*  20010420 VRS.  Tried it this way; failed.
 			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
 			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
 			**				kssl_ctx->length);
 			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
 			*/
 
 			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
 			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
 				kssl_ctx->key,iv);
 			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
 				sizeof tmp_buf);
 			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
 			outl += padl;
 			if (outl > (int)sizeof epms)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
 			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
 			s2n(outl,p);
 			memcpy(p, epms, outl);
 			p+=outl;
 			n+=outl + 2;
 
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf, sizeof tmp_buf);
 
 			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
 			OPENSSL_cleanse(epms, outl);
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 			{
 			DH *dh_srvr,*dh_clnt;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 				}
 
 			if (s->session->sess_cert->peer_dh_tmp != NULL)
 				dh_srvr=s->session->sess_cert->peer_dh_tmp;
 			else
 				{
 				/* we get them from the cert */
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
 				goto err;
 				}
 			
 			/* generate a new random key */
 			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 			if (!DH_generate_key(dh_clnt))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				DH_free(dh_clnt);
 				goto err;
 				}
 
 			/* use the 'p' output buffer for the DH key, but
 			 * make sure to clear it out afterwards */
 
 			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
 
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				DH_free(dh_clnt);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,p,n);
 			/* clean up */
 			memset(p,0,n);
 
 			/* send off the data */
 			n=BN_num_bytes(dh_clnt->pub_key);
 			s2n(n,p);
 			BN_bn2bin(dh_clnt->pub_key,p);
 			n+=2;
 
 			DH_free(dh_clnt);
 
 			/* perhaps clean things up a bit EAY EAY EAY EAY*/
 			}
 #endif
 
 #ifndef OPENSSL_NO_ECDH 
 		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
 			{
 			const EC_GROUP *srvr_group = NULL;
 			EC_KEY *tkey;
 			int ecdh_clnt_cert = 0;
 			int field_size = 0;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 				}
 
 			/* Did we send out the client's
 			 * ECDH share for use in premaster
 			 * computation as part of client certificate?
 			 * If so, set ecdh_clnt_cert to 1.
 			 */
 			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) 
 				{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates.
 				 * To add such support, one needs to add
 				 * code that checks for appropriate 
 				 * conditions and sets ecdh_clnt_cert to 1.
 				 * For example, the cert have an ECC
 				 * key on the same curve as the server's
 				 * and the key should be authorized for
 				 * key agreement.
 				 *
 				 * One also needs to add code in ssl3_connect
 				 * to skip sending the certificate verify
 				 * message.
 				 *
 				 * if ((s->cert->key->privatekey != NULL) &&
 				 *     (s->cert->key->privatekey->type ==
 				 *      EVP_PKEY_EC) && ...)
 				 * ecdh_clnt_cert = 1;
 				 */
 				}
 
 			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
 				{
 				tkey = s->session->sess_cert->peer_ecdh_tmp;
 				}
 			else
 				{
 				/* Get the Server Public Key from Cert */
 				srvr_pub_pkey = X509_get_pubkey(s->session-> \
 				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 				if ((srvr_pub_pkey == NULL) ||
 				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
 				    (srvr_pub_pkey->pkey.ec == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					    ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 
 				tkey = srvr_pub_pkey->pkey.ec;
 				}
 
 			srvr_group   = EC_KEY_get0_group(tkey);
 			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
 
 			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 				    ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 				goto err;
 				}
 			if (ecdh_clnt_cert) 
 				{ 
 				/* Reuse key info from our certificate
 				 * We only need our private key to perform
 				 * the ECDH computation.
 				 */
 				const BIGNUM *priv_key;
 				tkey = s->cert->key->privatekey->pkey.ec;
 				priv_key = EC_KEY_get0_private_key(tkey);
 				if (priv_key == NULL)
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 					goto err;
 					}
 				}
 			else 
 				{
 				/* Generate a new ECDH key pair */
 				if (!(EC_KEY_generate_key(clnt_ecdh)))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
 					goto err;
 					}
 				}
 
 			/* use the 'p' output buffer for the ECDH key, but
 			 * make sure to clear it out afterwards
 			 */
 
 			field_size = EC_GROUP_get_degree(srvr_group);
 			if (field_size <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length = s->method->ssl3_enc \
 			    -> generate_master_secret(s, 
 				s->session->master_key,
 				p, n);
 
 			memset(p, 0, n); /* clean up */
 
 			if (ecdh_clnt_cert) 
 				{
 				/* Send empty client key exch message */
 				n = 0;
 				}
 			else 
 				{
 				/* First check the size of encoding and
 				 * allocate memory accordingly.
 				 */
 				encoded_pt_len = 
 				    EC_POINT_point2oct(srvr_group, 
 					EC_KEY_get0_public_key(clnt_ecdh), 
 					POINT_CONVERSION_UNCOMPRESSED, 
 					NULL, 0, NULL);
 
 				encodedPoint = (unsigned char *) 
 				    OPENSSL_malloc(encoded_pt_len * 
 					sizeof(unsigned char)); 
 				bn_ctx = BN_CTX_new();
 				if ((encodedPoint == NULL) || 
 				    (bn_ctx == NULL)) 
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 
 				/* Encode the public key */
 				n = EC_POINT_point2oct(srvr_group, 
 				    EC_KEY_get0_public_key(clnt_ecdh), 
 				    POINT_CONVERSION_UNCOMPRESSED, 
 				    encodedPoint, encoded_pt_len, bn_ctx);
 
 				*p = n; /* length of encoded point */
 				/* Encoded point will be copied here */
 				p += 1; 
 				/* copy the point */
 				memcpy((unsigned char *)p, encodedPoint, n);
 				/* increment n to account for length field */
 				n += 1; 
 				}
 
 			/* Free allocated memory */
 			BN_CTX_free(bn_ctx);
 			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 			if (clnt_ecdh != NULL) 
 				 EC_KEY_free(clnt_ecdh);
 			EVP_PKEY_free(srvr_pub_pkey);
 			}
 #endif /* !OPENSSL_NO_ECDH */
 		else if (alg_k & SSL_kGOST) 
 			{
 			/* GOST key exchange message creation */
 			EVP_PKEY_CTX *pkey_ctx;
 			X509 *peer_cert; 
 			size_t msglen;
 			unsigned int md_len;
 			int keytype;
 			unsigned char premaster_secret[32],shared_ukm[32], tmp[256];
 			EVP_MD_CTX *ukm_hash;
 			EVP_PKEY *pub_key;
 
 			/* Get server sertificate PKEY and create ctx from it */
 			peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509;
 			if (!peer_cert) 
 				peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509;
 			if (!peer_cert)		{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
 					goto err;
 				}	
 				
 			pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL);
 			/* If we have send a certificate, and certificate key
 
 			 * parameters match those of server certificate, use
 			 * certificate key for key exchange
 			 */
 
 			 /* Otherwise, generate ephemeral key pair */
 					
 			EVP_PKEY_encrypt_init(pkey_ctx);
 			  /* Generate session key */	
 		    RAND_bytes(premaster_secret,32);
 			/* If we have client certificate, use its secret as peer key */
 			if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
 				if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
 					/* If there was an error - just ignore it. Ephemeral key
 					* would be used
 					*/
 					ERR_clear_error();
 				}
 			}			
 			/* Compute shared IV and store it in algorithm-specific
 			 * context data */
 			ukm_hash = EVP_MD_CTX_create();
 			EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94));
 			EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE);
 			EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE);
 			EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
 			EVP_MD_CTX_destroy(ukm_hash);
 			if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV,
 				8,shared_ukm)<0) {
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 						SSL_R_LIBRARY_BUG);
 					goto err;
 				}	
 			/* Make GOST keytransport blob message */
 			/*Encapsulate it into sequence */
 			*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
 			msglen=255;
 			if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					SSL_R_LIBRARY_BUG);
 				goto err;
 			}
 			if (msglen >= 0x80)
 				{
 				*(p++)=0x81;
 				*(p++)= msglen & 0xff;
 				n=msglen+3;
 				}
 			else
 				{
 				*(p++)= msglen & 0xff;
 				n=msglen+2;
 				}
 			memcpy(p, tmp, msglen);
 			/* Check if pubkey from client certificate was used */
 			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
 				{
 				/* Set flag "skip certificate verify" */
 				s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
 				}
 			EVP_PKEY_CTX_free(pkey_ctx);
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,premaster_secret,32);
 			EVP_PKEY_free(pub_key);
 
 			}
 #ifndef OPENSSL_NO_SRP
 		else if (alg_k & SSL_kSRP)
 			{
 			if (s->srp_ctx.A != NULL)
 				{
 				/* send off the data */
 				n=BN_num_bytes(s->srp_ctx.A);
 				s2n(n,p);
 				BN_bn2bin(s->srp_ctx.A,p);
 				n+=2;
 				}
 			else
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			if (s->session->srp_username != NULL)
 				OPENSSL_free(s->session->srp_username);
 			s->session->srp_username = BUF_strdup(s->srp_ctx.login);
 			if (s->session->srp_username == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			if ((s->session->master_key_length = SRP_generate_client_master_secret(s,s->session->master_key))<0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			}
 #endif
 #ifndef OPENSSL_NO_PSK
 		else if (alg_k & SSL_kPSK)
 			{
 			/* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes
 			 * to return a \0-terminated identity. The last byte
 			 * is for us for simulating strnlen. */
 			char identity[PSK_MAX_IDENTITY_LEN + 2];
 			size_t identity_len;
 			unsigned char *t = NULL;
 			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
 			unsigned int pre_ms_len = 0, psk_len = 0;
 			int psk_err = 1;
 
 			n = 0;
 			if (s->psk_client_callback == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					SSL_R_PSK_NO_CLIENT_CB);
 				goto err;
 				}
 
 			memset(identity, 0, sizeof(identity));
 			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
 				identity, sizeof(identity) - 1,
 				psk_or_pre_ms, sizeof(psk_or_pre_ms));
 			if (psk_len > PSK_MAX_PSK_LEN)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					ERR_R_INTERNAL_ERROR);
 				goto psk_err;
 				}
 			else if (psk_len == 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					SSL_R_PSK_IDENTITY_NOT_FOUND);
 				goto psk_err;
 				}
 			identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
 			identity_len = strlen(identity);
 			if (identity_len > PSK_MAX_IDENTITY_LEN)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					ERR_R_INTERNAL_ERROR);
 				goto psk_err;
 				}
 			/* create PSK pre_master_secret */
 			pre_ms_len = 2+psk_len+2+psk_len;
 			t = psk_or_pre_ms;
 			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
 			s2n(psk_len, t);
 			memset(t, 0, psk_len);
 			t+=psk_len;
 			s2n(psk_len, t);
 
 			if (s->session->psk_identity_hint != NULL)
 				OPENSSL_free(s->session->psk_identity_hint);
 			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
 			if (s->ctx->psk_identity_hint != NULL &&
 				s->session->psk_identity_hint == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto psk_err;
 				}
 
 			if (s->session->psk_identity != NULL)
 				OPENSSL_free(s->session->psk_identity);
 			s->session->psk_identity = BUF_strdup(identity);
 			if (s->session->psk_identity == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto psk_err;
 				}
 
 			s->session->master_key_length =
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					psk_or_pre_ms, pre_ms_len);
 			s2n(identity_len, p);
 			memcpy(p, identity, identity_len);
 			n = 2 + identity_len;
 			psk_err = 0;
 		psk_err:
 			OPENSSL_cleanse(identity, sizeof(identity));
 			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
 			if (psk_err != 0)
 				{
 				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
 				goto err;
 				}
 			}
 #endif
 		else
 			{
 			ssl3_send_alert(s, SSL3_AL_FATAL,
 			    SSL_AD_HANDSHAKE_FAILURE);
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 			    ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		
 		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_KEY_EXCH_B;
 		/* number of bytes to write */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_KEY_EXCH_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	if (clnt_ecdh != NULL) 
 		EC_KEY_free(clnt_ecdh);
 	EVP_PKEY_free(srvr_pub_pkey);
 #endif
 	return(-1);
 	}
 
 int ssl3_send_client_verify(SSL *s)
 	{
 	unsigned char *p,*d;
 	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	EVP_PKEY *pkey;
 	EVP_PKEY_CTX *pctx=NULL;
 	EVP_MD_CTX mctx;
 	unsigned u=0;
 	unsigned long n;
 	int j;
 
 	EVP_MD_CTX_init(&mctx);
 
 	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 		pkey=s->cert->key->privatekey;
 /* Create context from key and test if sha1 is allowed as digest */
 		pctx = EVP_PKEY_CTX_new(pkey,NULL);
 		EVP_PKEY_sign_init(pctx);
 		if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
 			{
 			if (TLS1_get_version(s) < TLS1_2_VERSION)
 				s->method->ssl3_enc->cert_verify_mac(s,
 						NID_sha1,
 						&(data[MD5_DIGEST_LENGTH]));
 			}
 		else
 			{
 			ERR_clear_error();
 			}
 		/* For TLS v1.2 send signature algorithm and signature
 		 * using agreed digest and cached handshake records.
 		 */
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
 			long hdatalen = 0;
 			void *hdata;
 			const EVP_MD *md = s->cert->key->digest;
 			hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
 								&hdata);
 			if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 						ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			p += 2;
 #ifdef SSL_DEBUG
 			fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
 							EVP_MD_name(md));
 #endif
 			if (!EVP_SignInit_ex(&mctx, md, NULL)
 				|| !EVP_SignUpdate(&mctx, hdata, hdatalen)
 				|| !EVP_SignFinal(&mctx, p + 2, &u, pkey))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 						ERR_R_EVP_LIB);
 				goto err;
 				}
 			s2n(u,p);
 			n = u + 4;
 			if (!ssl3_digest_cached_records(s))
 				goto err;
 			}
 		else
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA)
 			{
 			s->method->ssl3_enc->cert_verify_mac(s,
 				NID_md5,
 			 	&(data[0]));
 			if (RSA_sign(NID_md5_sha1, data,
 					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
 				goto err;
 				}
 			s2n(u,p);
 			n=u+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DSA
 			if (pkey->type == EVP_PKEY_DSA)
 			{
 			if (!DSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.dsa))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			if (pkey->type == EVP_PKEY_EC)
 			{
 			if (!ECDSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.ec))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 				    ERR_R_ECDSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 		if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001) 
 		{
 		unsigned char signbuf[64];
 		int i;
 		size_t sigsize=64;
 		s->method->ssl3_enc->cert_verify_mac(s,
 			NID_id_GostR3411_94,
 			data);
 		if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 			ERR_R_INTERNAL_ERROR);
 			goto err;
 		}
 		for (i=63,j=0; i>=0; j++, i--) {
 			p[2+j]=signbuf[i];
 		}	
 		s2n(j,p);
 		n=j+2;
 		}
 		else
 		{
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
 			goto err;
 		}
 		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_CERT_VRFY_B;
 		s->init_num=(int)n+4;
 		s->init_off=0;
 		}
 	EVP_MD_CTX_cleanup(&mctx);
 	EVP_PKEY_CTX_free(pctx);
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	EVP_MD_CTX_cleanup(&mctx);
 	EVP_PKEY_CTX_free(pctx);
 	return(-1);
 	}
 
 int ssl3_send_client_certificate(SSL *s)
 	{
 	X509 *x509=NULL;
 	EVP_PKEY *pkey=NULL;
 	int i;
 	unsigned long l;
 
 	if (s->state ==	SSL3_ST_CW_CERT_A)
 		{
 		if ((s->cert == NULL) ||
 			(s->cert->key->x509 == NULL) ||
 			(s->cert->key->privatekey == NULL))
 			s->state=SSL3_ST_CW_CERT_B;
 		else
 			s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	/* We need to get a client cert */
 	if (s->state == SSL3_ST_CW_CERT_B)
 		{
 		/* If we get an error, we need to
 		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
 		 * We then get retied later */
 		i=0;
 		i = ssl_do_client_cert_cb(s, &x509, &pkey);
 		if (i < 0)
 			{
 			s->rwstate=SSL_X509_LOOKUP;
 			return(-1);
 			}
 		s->rwstate=SSL_NOTHING;
 		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
 			{
 			s->state=SSL3_ST_CW_CERT_B;
 			if (	!SSL_use_certificate(s,x509) ||
 				!SSL_use_PrivateKey(s,pkey))
 				i=0;
 			}
 		else if (i == 1)
 			{
 			i=0;
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
 			}
 
 		if (x509 != NULL) X509_free(x509);
 		if (pkey != NULL) EVP_PKEY_free(pkey);
 		if (i == 0)
 			{
 			if (s->version == SSL3_VERSION)
 				{
 				s->s3->tmp.cert_req=0;
 				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
 				return(1);
 				}
 			else
 				{
 				s->s3->tmp.cert_req=2;
 				}
 			}
 
 		/* Ok, we have a cert */
 		s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	if (s->state == SSL3_ST_CW_CERT_C)
 		{
 		s->state=SSL3_ST_CW_CERT_D;
 		l=ssl3_output_cert_chain(s,
 			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
 		if (!l)
 			{
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
 			return 0;
 			}
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 	/* SSL3_ST_CW_CERT_D */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 #define has_bits(i,m)	(((i)&(m)) == (m))
 
 int ssl3_check_cert_and_algorithm(SSL *s)
 	{
 	int i,idx;
 	long alg_k,alg_a;
 	EVP_PKEY *pkey=NULL;
+	int pkey_bits;
 	SESS_CERT *sc;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh;
 #endif
+    int al = SSL_AD_HANDSHAKE_FAILURE;
 
 	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
 
 	/* we don't have a certificate */
 	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
 		return(1);
 
 	sc=s->session->sess_cert;
 	if (sc == NULL)
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 #ifndef OPENSSL_NO_RSA
 	rsa=s->session->sess_cert->peer_rsa_tmp;
 #endif
 #ifndef OPENSSL_NO_DH
 	dh=s->session->sess_cert->peer_dh_tmp;
 #endif
 
 	/* This is the passed certificate */
 
 	idx=sc->peer_cert_type;
 #ifndef OPENSSL_NO_ECDH
 	if (idx == SSL_PKEY_ECC)
 		{
 		if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
 		    						s) == 0) 
 			{ /* check failed */
 			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
 			goto f_err;
 			}
 		else 
 			{
 			return 1;
 			}
 		}
 #endif
 	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
+	pkey_bits = EVP_PKEY_bits(pkey);
 	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
 	EVP_PKEY_free(pkey);
 
 	
 	/* Check that we have a certificate if we require one */
 	if ((alg_a & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_DSA
 	else if ((alg_a & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
 		goto f_err;
 		}
 #endif
 #ifndef OPENSSL_NO_RSA
-	if ((alg_k & SSL_kRSA) &&
-		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
-		{
-		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+    if (alg_k & SSL_kRSA) {
+        if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+            !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                   SSL_R_MISSING_RSA_ENCRYPTING_CERT);
 		goto f_err;
+        } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
+            if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                           SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+                    goto f_err;
 		}
+                if (rsa != NULL) {
+                    /* server key exchange is not allowed. */
+                    al = SSL_AD_INTERNAL_ERROR;
+                    SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
+                    goto f_err;
+                }
+            }
+        }
+    }
 #endif
 #ifndef OPENSSL_NO_DH
-	if ((alg_k & SSL_kEDH) &&
-		!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
-		{
-		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
+    if ((alg_k & SSL_kEDH) && dh == NULL) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
 		goto f_err;
 		}
-	else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
-		{
-		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
+    if ((alg_k & SSL_kDHr) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) {
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+               SSL_R_MISSING_DH_RSA_CERT);
 		goto f_err;
 		}
-#ifndef OPENSSL_NO_DSA
-	else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
-		{
-		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
+# ifndef OPENSSL_NO_DSA
+    if ((alg_k & SSL_kDHd) && !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) {
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+               SSL_R_MISSING_DH_DSA_CERT);
 		goto f_err;
 		}
-#endif
-#endif
+# endif
 
-	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
+    /* Check DHE only: static DH not implemented. */
+    if (alg_k & SSL_kEDH) {
+        int dh_size = BN_num_bits(dh->p);
+        if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768)
+            || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) {
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL);
+            goto f_err;
+        }
+    }
+#endif  /* !OPENSSL_NO_DH */
+
+	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+	    pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
 		{
 #ifndef OPENSSL_NO_RSA
-		if (alg_k & SSL_kRSA)
-			{
-			if (rsa == NULL
-			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
-				{
-				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+        if (alg_k & SSL_kRSA) {
+            if (rsa == NULL) {
+                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                       SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
 				goto f_err;
+            } else if (BN_num_bits(rsa->n) >
+                SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                /* We have a temporary RSA key but it's too large. */
+                al = SSL_AD_EXPORT_RESTRICTION;
+                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                       SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
+                goto f_err;
 				}
-			}
-		else
+        } else
 #endif
 #ifndef OPENSSL_NO_DH
-			if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
-			    {
-			    if (dh == NULL
-				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
-				{
-				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
+        if (alg_k & SSL_kEDH) {
+            if (BN_num_bits(dh->p) >
+                SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
+                /* We have a temporary DH key but it's too large. */
+                al = SSL_AD_EXPORT_RESTRICTION;
+                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                       SSL_R_MISSING_EXPORT_TMP_DH_KEY);
 				goto f_err;
 				}
-			}
-		else
+        } else if (alg_k & (SSL_kDHr | SSL_kDHd)) {
+            /* The cert should have had an export DH key. */
+            al = SSL_AD_EXPORT_RESTRICTION;
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                   SSL_R_MISSING_EXPORT_TMP_DH_KEY);
+                goto f_err;
+        } else
 #endif
 			{
-			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+            SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                   SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		}
-	return(1);
-f_err:
-	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
-err:
-	return(0);
-	}
+    return (1);
+ f_err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+    return (0);
+}
 
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
 int ssl3_send_next_proto(SSL *s)
 	{
 	unsigned int len, padding_len;
 	unsigned char *d;
 
 	if (s->state == SSL3_ST_CW_NEXT_PROTO_A)
 		{
 		len = s->next_proto_negotiated_len;
 		padding_len = 32 - ((len + 2) % 32);
 		d = (unsigned char *)s->init_buf->data;
 		d[4] = len;
 		memcpy(d + 5, s->next_proto_negotiated, len);
 		d[5 + len] = padding_len;
 		memset(d + 6 + len, 0, padding_len);
 		*(d++)=SSL3_MT_NEXT_PROTO;
 		l2n3(2 + len + padding_len, d);
 		s->state = SSL3_ST_CW_NEXT_PROTO_B;
 		s->init_num = 4 + 2 + len + padding_len;
 		s->init_off = 0;
 		}
 
 	return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
         }
 #endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
 
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 	{
 	int i = 0;
 #ifndef OPENSSL_NO_ENGINE
 	if (s->ctx->client_cert_engine)
 		{
 		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
 						SSL_get_client_CA_list(s),
 						px509, ppkey, NULL, NULL, NULL);
 		if (i != 0)
 			return i;
 		}
 #endif
 	if (s->ctx->client_cert_cb)
 		i = s->ctx->client_cert_cb(s,px509,ppkey);
 	return i;
 	}
Index: releng/10.1/crypto/openssl/ssl/s3_srvr.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/s3_srvr.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/s3_srvr.c	(revision 284295)
@@ -1,3675 +1,3686 @@
 /* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 /* ====================================================================
  * Copyright 2005 Nokia. All rights reserved.
  *
  * The portions of the attached software ("Contribution") is developed by
  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
  * license.
  *
  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
  * support (see RFC 4279) to OpenSSL.
  *
  * No patent licenses or other rights except those expressly stated in
  * the OpenSSL open source license shall be deemed granted or received
  * expressly, by implication, estoppel, or otherwise.
  *
  * No assurances are provided by Nokia that the Contribution does not
  * infringe the patent or other intellectual property rights of any third
  * party or that the license provides you with all the necessary rights
  * to make use of the Contribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
 
 #define REUSE_CIPHER_BUG
 #define NETSCAPE_HANG_BUG
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include "../crypto/constant_time_locl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_KRB5
 #include 
 #endif
 #include 
 
 #ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_server_method(int ver);
 
 static const SSL_METHOD *ssl3_get_server_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_server_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
 			ssl3_accept,
 			ssl_undefined_function,
 			ssl3_get_server_method)
 #endif
 
 #ifndef OPENSSL_NO_SRP
 static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
 	{
 	int ret = SSL_ERROR_NONE;
 
 	*al = SSL_AD_UNRECOGNIZED_NAME;
 
 	if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
 	    (s->srp_ctx.TLS_ext_srp_username_callback != NULL))
 		{
 		if(s->srp_ctx.login == NULL)
 			{
 			/* RFC 5054 says SHOULD reject, 
 			   we do so if There is no srp login name */
 			ret = SSL3_AL_FATAL;
 			*al = SSL_AD_UNKNOWN_PSK_IDENTITY;
 			}
 		else
 			{
 			ret = SSL_srp_server_param_with_username(s,al);
 			}
 		}
 	return ret;
 	}
 #endif
 
 int ssl3_accept(SSL *s)
 	{
 	BUF_MEM *buf;
 	unsigned long alg_k,Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 
 	/* init things to blank */
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
 
 	if (s->cert == NULL)
 		{
 		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
 		return(-1);
 		}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	/* If we're awaiting a HeartbeatResponse, pretend we
 	 * already got and don't await it anymore, because
 	 * Heartbeats don't make sense during handshakes anyway.
 	 */
 	if (s->tlsext_hb_pending)
 		{
 		s->tlsext_hb_pending = 0;
 		s->tlsext_hb_seq++;
 		}
 #endif
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch (s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->renegotiate=1;
 			/* s->state=SSL_ST_ACCEPT; */
 
 		case SSL_ST_BEFORE:
 		case SSL_ST_ACCEPT:
 		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
 		case SSL_ST_OK|SSL_ST_ACCEPT:
 
 			s->server=1;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version>>8) != 3)
 				{
 				SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
 				return -1;
 				}
 			s->type=SSL_ST_ACCEPT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					BUF_MEM_free(buf);
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				}
 
 			if (!ssl3_setup_buffers(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			s->init_num=0;
 			s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
 			s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
 			/* Should have been reset by ssl3_get_finished, too. */
 			s->s3->change_cipher_spec = 0;
 
 			if (s->state != SSL_ST_RENEGOTIATE)
 				{
 				/* Ok, we now need to push on a buffering BIO so that
 				 * the output is sent in a way that TCP likes :-)
 				 */
 				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
 				
 				ssl3_init_finished_mac(s);
 				s->state=SSL3_ST_SR_CLNT_HELLO_A;
 				s->ctx->stats.sess_accept++;
 				}
 			else if (!s->s3->send_connection_binding &&
 				!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
 				{
 				/* Server attempting to renegotiate with
 				 * client that doesn't support secure
 				 * renegotiation.
 				 */
 				SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				ret = -1;
 				goto end;
 				}
 			else
 				{
 				/* s->state == SSL_ST_RENEGOTIATE,
 				 * we will just send a HelloRequest */
 				s->ctx->stats.sess_accept_renegotiate++;
 				s->state=SSL3_ST_SW_HELLO_REQ_A;
 				}
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_A:
 		case SSL3_ST_SW_HELLO_REQ_B:
 
 			s->shutdown=0;
 			ret=ssl3_send_hello_request(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 
 			ssl3_init_finished_mac(s);
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_C:
 			s->state=SSL_ST_OK;
 			break;
 
 		case SSL3_ST_SR_CLNT_HELLO_A:
 		case SSL3_ST_SR_CLNT_HELLO_B:
 		case SSL3_ST_SR_CLNT_HELLO_C:
 
 			s->shutdown=0;
 			if (s->rwstate != SSL_X509_LOOKUP)
 			{
 				ret=ssl3_get_client_hello(s);
 				if (ret <= 0) goto end;
 			}
 #ifndef OPENSSL_NO_SRP
 			{
 			int al;
 			if ((ret = ssl_check_srp_ext_ClientHello(s,&al))  < 0)
 					{
 					/* callback indicates firther work to be done */
 					s->rwstate=SSL_X509_LOOKUP;
 					goto end;
 					}
 			if (ret != SSL_ERROR_NONE)
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,al);	
 				/* This is not really an error but the only means to
                                    for a client to detect whether srp is supported. */
  				   if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY) 	
 					SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT);			
 				ret = SSL_TLSEXT_ERR_ALERT_FATAL;			
 				ret= -1;
 				goto end;	
 				}
 			}
 #endif		
 			
 			s->renegotiate = 2;
 			s->state=SSL3_ST_SW_SRVR_HELLO_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_SRVR_HELLO_A:
 		case SSL3_ST_SW_SRVR_HELLO_B:
 			ret=ssl3_send_server_hello(s);
 			if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 			if (s->hit)
 				{
 				if (s->tlsext_ticket_expected)
 					s->state=SSL3_ST_SW_SESSION_TICKET_A;
 				else
 					s->state=SSL3_ST_SW_CHANGE_A;
 				}
 #else
 			if (s->hit)
 					s->state=SSL3_ST_SW_CHANGE_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_A:
 		case SSL3_ST_SW_CERT_B:
 			/* Check if it is anon DH or anon ECDH, */
 			/* normal PSK or KRB5 or SRP */
 			if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP))
 				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
 				{
 				ret=ssl3_send_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_SW_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_KEY_EXCH_A:
 		case SSL3_ST_SW_KEY_EXCH_B:
 			alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
 			/*
 			 * clear this, it may get reset by
 			 * send_server_key_exchange
 			 */
 			s->s3->tmp.use_rsa_tmp=0;
 
 
 			/* only send if a DH key exchange, fortezza or
 			 * RSA but we have a sign only certificate
 			 *
 			 * PSK: may send PSK identity hints
 			 *
 			 * For ECC ciphersuites, we send a serverKeyExchange
 			 * message only if the cipher suite is either
 			 * ECDH-anon or ECDHE. In other cases, the
 			 * server certificate contains the server's
 			 * public key for key exchange.
 			 */
 			if (0
 			/* PSK: send ServerKeyExchange if PSK identity
 			 * hint if provided */
 #ifndef OPENSSL_NO_PSK
 			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
 #endif
 #ifndef OPENSSL_NO_SRP
 			    /* SRP: send ServerKeyExchange */
 			    || (alg_k & SSL_kSRP)
 #endif
 			    || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH))
 			    || (alg_k & SSL_kEECDH)
 			    || ((alg_k & SSL_kRSA)
 				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
 				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
 					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
 					)
 				    )
 				)
 			    )
 				{
 				ret=ssl3_send_server_key_exchange(s);
 				if (ret <= 0) goto end;
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_CERT_REQ_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_REQ_A:
 		case SSL3_ST_SW_CERT_REQ_B:
 			if (/* don't request cert unless asked for it: */
 				!(s->verify_mode & SSL_VERIFY_PEER) ||
 				/* if SSL_VERIFY_CLIENT_ONCE is set,
 				 * don't request cert during re-negotiation: */
 				((s->session->peer != NULL) &&
 				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
 				/* never request cert in anonymous ciphersuites
 				 * (see section "Certificate request" in SSL 3 drafts
 				 * and in RFC 2246): */
 				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
 				 /* ... except when the application insists on verification
 				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
 				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
 				 /* never request cert in Kerberos ciphersuites */
 				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) ||
 				/* don't request certificate for SRP auth */
 				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
 				/* With normal PSK Certificates and
 				 * Certificate Requests are omitted */
 				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
 				{
 				/* no cert request */
 				skip=1;
 				s->s3->tmp.cert_request=0;
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 				if (s->s3->handshake_buffer)
 					if (!ssl3_digest_cached_records(s))
 						return -1;
 				}
 			else
 				{
 				s->s3->tmp.cert_request=1;
 				ret=ssl3_send_certificate_request(s);
 				if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 #else
 				s->state=SSL3_ST_SW_FLUSH;
 				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 #endif
 				s->init_num=0;
 				}
 			break;
 
 		case SSL3_ST_SW_SRVR_DONE_A:
 		case SSL3_ST_SW_SRVR_DONE_B:
 			ret=ssl3_send_server_done(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 			break;
 		
 		case SSL3_ST_SW_FLUSH:
 
 			/* This code originally checked to see if
 			 * any data was pending using BIO_CTRL_INFO
 			 * and then flushed. This caused problems
 			 * as documented in PR#1939. The proposed
 			 * fix doesn't completely resolve this issue
 			 * as buggy implementations of BIO_CTRL_PENDING
 			 * still exist. So instead we just flush
 			 * unconditionally.
 			 */
 
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL3_ST_SR_CERT_A:
 		case SSL3_ST_SR_CERT_B:
 			/* Check for second client hello (MS SGC) */
 			ret = ssl3_check_client_hello(s);
 			if (ret <= 0)
 				goto end;
 			if (ret == 2)
 				s->state = SSL3_ST_SR_CLNT_HELLO_C;
 			else {
 				if (s->s3->tmp.cert_request)
 					{
 					ret=ssl3_get_client_certificate(s);
 					if (ret <= 0) goto end;
 					}
 				s->init_num=0;
 				s->state=SSL3_ST_SR_KEY_EXCH_A;
 			}
 			break;
 
 		case SSL3_ST_SR_KEY_EXCH_A:
 		case SSL3_ST_SR_KEY_EXCH_B:
 			ret=ssl3_get_client_key_exchange(s);
 			if (ret <= 0)
 				goto end;
 			if (ret == 2)
 				{
 				/* For the ECDH ciphersuites when
 				 * the client sends its ECDH pub key in
 				 * a certificate, the CertificateVerify
 				 * message is not sent.
 				 * Also for GOST ciphersuites when
 				 * the client uses its key from the certificate
 				 * for key exchange.
 				 */
 #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
 				s->state=SSL3_ST_SR_FINISHED_A;
 #else
 				if (s->s3->next_proto_neg_seen)
 					s->state=SSL3_ST_SR_NEXT_PROTO_A;
 				else
 					s->state=SSL3_ST_SR_FINISHED_A;
 #endif
 				s->init_num = 0;
 				}
 			else if (TLS1_get_version(s) >= TLS1_2_VERSION)
 				{
 				s->state=SSL3_ST_SR_CERT_VRFY_A;
 				s->init_num=0;
 				if (!s->session->peer)
 					break;
 				/* For TLS v1.2 freeze the handshake buffer
 				 * at this point and digest cached records.
 				 */
 				if (!s->s3->handshake_buffer)
 					{
 					SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
 					return -1;
 					}
 				s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
 				if (!ssl3_digest_cached_records(s))
 					return -1;
 				}
 			else
 				{
 				int offset=0;
 				int dgst_num;
 
 				s->state=SSL3_ST_SR_CERT_VRFY_A;
 				s->init_num=0;
 
 				/* We need to get hashes here so if there is
 				 * a client cert, it can be verified
 				 * FIXME - digest processing for CertificateVerify
 				 * should be generalized. But it is next step
 				 */
 				if (s->s3->handshake_buffer)
 					if (!ssl3_digest_cached_records(s))
 						return -1;
 				for (dgst_num=0; dgst_nums3->handshake_dgst[dgst_num]) 
 						{
 						int dgst_size;
 
 						s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
 						dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
 						if (dgst_size < 0)
 							{
 							ret = -1;
 							goto end;
 							}
 						offset+=dgst_size;
 						}		
 				}
 			break;
 
 		case SSL3_ST_SR_CERT_VRFY_A:
 		case SSL3_ST_SR_CERT_VRFY_B:
 			/*
 			 * This *should* be the first time we enable CCS, but be
 			 * extra careful about surrounding code changes. We need
 			 * to set this here because we don't know if we're
 			 * expecting a CertificateVerify or not.
 			 */
 			if (!s->s3->change_cipher_spec)
 				s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			/* we should decide if we expected this one */
 			ret=ssl3_get_cert_verify(s);
 			if (ret <= 0) goto end;
 
 #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
 			s->state=SSL3_ST_SR_FINISHED_A;
 #else
 			if (s->s3->next_proto_neg_seen)
 				s->state=SSL3_ST_SR_NEXT_PROTO_A;
 			else
 				s->state=SSL3_ST_SR_FINISHED_A;
 #endif
 			s->init_num=0;
 			break;
 
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
 		case SSL3_ST_SR_NEXT_PROTO_A:
 		case SSL3_ST_SR_NEXT_PROTO_B:
 			/*
 			 * Enable CCS for resumed handshakes with NPN.
 			 * In a full handshake with NPN, we end up here through
 			 * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
 			 * already set. Receiving a CCS clears the flag, so make
 			 * sure not to re-enable it to ban duplicates.
 			 * s->s3->change_cipher_spec is set when a CCS is
 			 * processed in s3_pkt.c, and remains set until
 			 * the client's Finished message is read.
 			 */
 			if (!s->s3->change_cipher_spec)
 				s->s3->flags |= SSL3_FLAGS_CCS_OK;
 
 			ret=ssl3_get_next_proto(s);
 			if (ret <= 0) goto end;
 			s->init_num = 0;
 			s->state=SSL3_ST_SR_FINISHED_A;
 			break;
 #endif
 
 		case SSL3_ST_SR_FINISHED_A:
 		case SSL3_ST_SR_FINISHED_B:
 			/*
 			 * Enable CCS for resumed handshakes without NPN.
 			 * In a full handshake, we end up here through
 			 * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
 			 * already set. Receiving a CCS clears the flag, so make
 			 * sure not to re-enable it to ban duplicates.
 			 * s->s3->change_cipher_spec is set when a CCS is
 			 * processed in s3_pkt.c, and remains set until
 			 * the client's Finished message is read.
 			 */
 			if (!s->s3->change_cipher_spec)
 				s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
 				SSL3_ST_SR_FINISHED_B);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				s->state=SSL_ST_OK;
 #ifndef OPENSSL_NO_TLSEXT
 			else if (s->tlsext_ticket_expected)
 				s->state=SSL3_ST_SW_SESSION_TICKET_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_SW_SESSION_TICKET_A:
 		case SSL3_ST_SW_SESSION_TICKET_B:
 			ret=ssl3_send_newsession_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_STATUS_A:
 		case SSL3_ST_SW_CERT_STATUS_B:
 			ret=ssl3_send_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 #endif
 
 		case SSL3_ST_SW_CHANGE_A:
 		case SSL3_ST_SW_CHANGE_B:
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{ ret= -1; goto end; }
 
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
 
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FINISHED_A;
 			s->init_num=0;
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_SERVER_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 		case SSL3_ST_SW_FINISHED_A:
 		case SSL3_ST_SW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
 				s->method->ssl3_enc->server_finished_label,
 				s->method->ssl3_enc->server_finished_label_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
 				{
 #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
 				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
 #else
 				if (s->s3->next_proto_neg_seen)
 					{
 					s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
 					}
 				else
 					s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
 #endif
 				}
 			else
 				s->s3->tmp.next_state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			BUF_MEM_free(s->init_buf);
 			s->init_buf=NULL;
 
 			/* remove buffering on output */
 			ssl_free_wbio_buffer(s);
 
 			s->init_num=0;
 
 			if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
 				{
 				s->renegotiate=0;
 				s->new_session=0;
 				
 				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
 				
 				s->ctx->stats.sess_accept_good++;
 				/* s->server=1; */
 				s->handshake_func=ssl3_accept;
 
 				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 				}
 			
 			ret = 1;
 			goto end;
 			/* break; */
 
 		default:
 			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 		
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_ACCEPT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	/* BIO_flush(s->wbio); */
 
 	s->in_handshake--;
 	if (cb != NULL)
 		cb(s,SSL_CB_ACCEPT_EXIT,ret);
 	return(ret);
 	}
 
 int ssl3_send_hello_request(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 		*(p++)=SSL3_MT_HELLO_REQUEST;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_HELLO_REQ_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_HELLO_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_check_client_hello(SSL *s)
 	{
 	int ok;
 	long n;
 
 	/* this function is called when we really expect a Certificate message,
 	 * so permit appropriate message length */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 	s->s3->tmp.reuse_message = 1;
 	if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
 		{
 		/* We only allow the client to restart the handshake once per
 		 * negotiation. */
 		if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
 			{
 			SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
 			return -1;
 			}
 		/* Throw away what we have done so far in the current handshake,
 		 * which will now be aborted. (A full SSL_clear would be too much.) */
 #ifndef OPENSSL_NO_DH
 		if (s->s3->tmp.dh != NULL)
 			{
 			DH_free(s->s3->tmp.dh);
 			s->s3->tmp.dh = NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->s3->tmp.ecdh != NULL)
 			{
 			EC_KEY_free(s->s3->tmp.ecdh);
 			s->s3->tmp.ecdh = NULL;
 			}
 #endif
 		s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
 		return 2;
 		}
 	return 1;
 }
 
 int ssl3_get_client_hello(SSL *s)
 	{
 	int i,j,ok,al,ret= -1;
 	unsigned int cookie_len;
 	long n;
 	unsigned long id;
 	unsigned char *p,*d,*q;
 	SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp=NULL;
 #endif
 	STACK_OF(SSL_CIPHER) *ciphers=NULL;
 
 	/* We do this so that we will respond with our native type.
 	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
 	 * This down switching should be handled by a different method.
 	 * If we are SSLv3, we will respond with SSLv3, even if prompted with
 	 * TLSv1.
 	 */
 	if (s->state == SSL3_ST_SR_CLNT_HELLO_A
 		)
 		{
 		s->state=SSL3_ST_SR_CLNT_HELLO_B;
 		}
 	s->first_packet=1;
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CLNT_HELLO_B,
 		SSL3_ST_SR_CLNT_HELLO_C,
 		SSL3_MT_CLIENT_HELLO,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 	s->first_packet=0;
 	d=p=(unsigned char *)s->init_msg;
 
 	/* use version from inside client hello, not from record header
 	 * (may differ: see RFC 2246, Appendix E, second paragraph) */
 	s->client_version=(((int)p[0])<<8)|(int)p[1];
 	p+=2;
 
 	if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
 	    (s->version != DTLS1_VERSION && s->client_version < s->version))
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
 		if ((s->client_version>>8) == SSL3_VERSION_MAJOR && 
 			!s->enc_write_ctx && !s->write_hash)
 			{
 			/* similar to ssl3_get_record, send alert using remote version number */
 			s->version = s->client_version;
 			}
 		al = SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 
 	/* If we require cookies and this ClientHello doesn't
 	 * contain one, just return since we do not want to
 	 * allocate any memory yet. So check cookie length...
 	 */
 	if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
 		{
 		unsigned int session_length, cookie_length;
 		
 		session_length = *(p + SSL3_RANDOM_SIZE);
 		cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
 
 		if (cookie_length == 0)
 			return 1;
 		}
 
 	/* load the client random */
 	memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	/* get the session-id */
 	j= *(p++);
 
 	s->hit=0;
 	/* Versions before 0.9.7 always allow clients to resume sessions in renegotiation.
 	 * 0.9.7 and later allow this by default, but optionally ignore resumption requests
 	 * with flag SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather
 	 * than a change to default behavior so that applications relying on this for security
 	 * won't even compile against older library versions).
 	 *
 	 * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to request
 	 * renegotiation but not a new session (s->new_session remains unset): for servers,
 	 * this essentially just means that the SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
 	 * setting will be ignored.
 	 */
 	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
 		{
 		if (!ssl_get_new_session(s,1))
 			goto err;
 		}
 	else
 		{
 		i=ssl_get_prev_session(s, p, j, d + n);
 		/*
 		 * Only resume if the session's version matches the negotiated
 		 * version.
 		 * RFC 5246 does not provide much useful advice on resumption
 		 * with a different protocol version. It doesn't forbid it but
 		 * the sanity of such behaviour would be questionable.
 		 * In practice, clients do not accept a version mismatch and
 		 * will abort the handshake with an error.
 		 */
 		if (i == 1 && s->version == s->session->ssl_version)
 			{ /* previous session */
 			s->hit=1;
 			}
 		else if (i == -1)
 			goto err;
 		else /* i == 0 */
 			{
 			if (!ssl_get_new_session(s,1))
 				goto err;
 			}
 		}
 
 	p+=j;
 
 	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
 		{
 		/* cookie stuff */
 		cookie_len = *(p++);
 
 		/* 
 		 * The ClientHello may contain a cookie even if the
 		 * HelloVerify message has not been sent--make sure that it
 		 * does not cause an overflow.
 		 */
 		if ( cookie_len > sizeof(s->d1->rcvd_cookie))
 			{
 			/* too much data */
 			al = SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
 			goto f_err;
 			}
 
 		/* verify the cookie if appropriate option is set. */
 		if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
 			cookie_len > 0)
 			{
 			memcpy(s->d1->rcvd_cookie, p, cookie_len);
 
 			if ( s->ctx->app_verify_cookie_cb != NULL)
 				{
 				if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
 					cookie_len) == 0)
 					{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 					}
 				/* else cookie verification succeeded */
 				}
 			else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, 
 						  s->d1->cookie_len) != 0) /* default verification */
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 				}
 
 			ret = 2;
 			}
 
 		p += cookie_len;
 		}
 
 	n2s(p,i);
 	if ((i == 0) && (j != 0))
 		{
 		/* we need a cipher if we are not resuming a session */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);
 		goto f_err;
 		}
 	if ((p+i) >= (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))
 		== NULL))
 		{
 		goto err;
 		}
 	p+=i;
 
 	/* If it is a hit, check that the cipher is in the list */
 	if ((s->hit) && (i > 0))
 		{
 		j=0;
 		id=s->session->cipher->id;
 
 #ifdef CIPHER_DEBUG
 		fprintf(stderr,"client sent %d ciphers\n",sk_SSL_CIPHER_num(ciphers));
 #endif
 		for (i=0; iid == id)
 				{
 				j=1;
 				break;
 				}
 			}
 /* Disabled because it can be used in a ciphersuite downgrade
  * attack: CVE-2010-4180.
  */
 #if 0
 		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
 			{
 			/* Special case as client bug workaround: the previously used cipher may
 			 * not be in the current list, the client instead might be trying to
 			 * continue using a cipher that before wasn't chosen due to server
 			 * preferences.  We'll have to reject the connection if the cipher is not
 			 * enabled, though. */
 			c = sk_SSL_CIPHER_value(ciphers, 0);
 			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
 				{
 				s->session->cipher = c;
 				j = 1;
 				}
 			}
 #endif
 		if (j == 0)
 			{
 			/* we need to have the cipher in the cipher
 			 * list if we are asked to reuse it */
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
 			goto f_err;
 			}
 		}
 
 	/* compression */
 	i= *(p++);
 	if ((p+i) > (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	q=p;
 	for (j=0; j= i)
 		{
 		/* no compress */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_clienthello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err;
 			}
 		}
 		if (ssl_check_clienthello_tlsext_early(s) <= 0) {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 		}
 
 	/* Check if we want to use external pre-shared secret for this
 	 * handshake for not reused session only. We need to generate
 	 * server_random before calling tls_session_secret_cb in order to allow
 	 * SessionTicket processing to use it in key derivation. */
 	{
 		unsigned char *pos;
 		pos=s->s3->server_random;
 		if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0)
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			goto f_err;
 			}
 	}
 
 	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
 		{
 		SSL_CIPHER *pref_cipher=NULL;
 
 		s->session->master_key_length=sizeof(s->session->master_key);
 		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
 			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
 			{
 			s->hit=1;
 			s->session->ciphers=ciphers;
 			s->session->verify_result=X509_V_OK;
 
 			ciphers=NULL;
 
 			/* check if some cipher was preferred by call back */
 			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
 			if (pref_cipher == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
 				goto f_err;
 				}
 
 			s->session->cipher=pref_cipher;
 
 			if (s->cipher_list)
 				sk_SSL_CIPHER_free(s->cipher_list);
 
 			if (s->cipher_list_by_id)
 				sk_SSL_CIPHER_free(s->cipher_list_by_id);
 
 			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
 			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
 			}
 		}
 #endif
 
 	/* Worst case, we will use the NULL compression, but if we have other
 	 * options, we will now look for them.  We have i-1 compression
 	 * algorithms from the client, starting at q. */
 	s->s3->tmp.new_compression=NULL;
 #ifndef OPENSSL_NO_COMP
 	/* This only happens if we have a cache hit */
 	if (s->session->compress_meth != 0)
 		{
 		int m, comp_id = s->session->compress_meth;
 		/* Perform sanity checks on resumed compression algorithm */
 		/* Can't disable compression */
 		if (s->options & SSL_OP_NO_COMPRESSION)
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
 			goto f_err;
 			}
 		/* Look for resumed compression method */
 		for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++)
 			{
 			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m);
 			if (comp_id == comp->id)
 				{
 				s->s3->tmp.new_compression=comp;
 				break;
 				}
 			}
 		if (s->s3->tmp.new_compression == NULL)
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM);
 			goto f_err;
 			}
 		/* Look for resumed method in compression list */
 		for (m = 0; m < i; m++)
 			{
 			if (q[m] == comp_id)
 				break;
 			}
 		if (m >= i)
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
 			goto f_err;
 			}
 		}
 	else if (s->hit)
 		comp = NULL;
 	else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
 		{ /* See if we have a match */
 		int m,nn,o,v,done=0;
 
 		nn=sk_SSL_COMP_num(s->ctx->comp_methods);
 		for (m=0; mctx->comp_methods,m);
 			v=comp->id;
 			for (o=0; os3->tmp.new_compression=comp;
 		else
 			comp=NULL;
 		}
 #else
 	/* If compression is disabled we'd better not try to resume a session
 	 * using compression.
 	 */
 	if (s->session->compress_meth != 0)
 		{
 		al=SSL_AD_INTERNAL_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
 		goto f_err;
 		}
 #endif
 
 	/* Given s->session->ciphers and SSL_get_ciphers, we must
 	 * pick a cipher */
 
 	if (!s->hit)
 		{
 #ifdef OPENSSL_NO_COMP
 		s->session->compress_meth=0;
 #else
 		s->session->compress_meth=(comp == NULL)?0:comp->id;
 #endif
 		if (s->session->ciphers != NULL)
 			sk_SSL_CIPHER_free(s->session->ciphers);
 		s->session->ciphers=ciphers;
 		if (ciphers == NULL)
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);
 			goto f_err;
 			}
 		ciphers=NULL;
 		c=ssl3_choose_cipher(s,s->session->ciphers,
 				     SSL_get_ciphers(s));
 
 		if (c == NULL)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
 			goto f_err;
 			}
 		s->s3->tmp.new_cipher=c;
 		}
 	else
 		{
 		/* Session-id reuse */
 #ifdef REUSE_CIPHER_BUG
 		STACK_OF(SSL_CIPHER) *sk;
 		SSL_CIPHER *nc=NULL;
 		SSL_CIPHER *ec=NULL;
 
 		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
 			{
 			sk=s->session->ciphers;
 			for (i=0; ialgorithm_enc & SSL_eNULL)
 					nc=c;
 				if (SSL_C_IS_EXPORT(c))
 					ec=c;
 				}
 			if (nc != NULL)
 				s->s3->tmp.new_cipher=nc;
 			else if (ec != NULL)
 				s->s3->tmp.new_cipher=ec;
 			else
 				s->s3->tmp.new_cipher=s->session->cipher;
 			}
 		else
 #endif
 		s->s3->tmp.new_cipher=s->session->cipher;
 		}
 
 	if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER))
 		{
 		if (!ssl3_digest_cached_records(s))
 			{
 			al = SSL_AD_INTERNAL_ERROR;
 			goto f_err;
 			}
 		}
 	
 	/* we now have the following setup. 
 	 * client_random
 	 * cipher_list 		- our prefered list of ciphers
 	 * ciphers 		- the clients prefered list of ciphers
 	 * compression		- basically ignored right now
 	 * ssl version is set	- sslv3
 	 * s->session		- The ssl session has been setup.
 	 * s->hit		- session reuse flag
 	 * s->tmp.new_cipher	- the new cipher to use.
 	 */
 
 	/* Handles TLS extensions that we couldn't check earlier */
 	if (s->version >= SSL3_VERSION)
 		{
 		if (ssl_check_clienthello_tlsext_late(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 			}
 		}
 
 	if (ret < 0) ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
 	return(ret);
 	}
 
 int ssl3_send_server_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i,sl;
 	unsigned long l;
 
 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
 		{
 		buf=(unsigned char *)s->init_buf->data;
 #ifdef OPENSSL_NO_TLSEXT
 		p=s->s3->server_random;
 		if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0)
 			return -1;
 #endif
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 
 		/* Random stuff */
 		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* There are several cases for the session ID to send
 		 * back in the server hello:
 		 * - For session reuse from the session cache,
 		 *   we send back the old session ID.
 		 * - If stateless session reuse (using a session ticket)
 		 *   is successful, we send back the client's "session ID"
 		 *   (which doesn't actually identify the session).
 		 * - If it is a new session, we send back the new
 		 *   session ID.
 		 * - However, if we want the new session to be single-use,
 		 *   we send back a 0-length session ID.
 		 * s->hit is non-zero in either case of session reuse,
 		 * so the following won't overwrite an ID that we're supposed
 		 * to send back.
 		 */
 		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
 			&& !s->hit)
 			s->session->session_id_length=0;
 
 		sl=s->session->session_id_length;
 		if (sl > (int)sizeof(s->session->session_id))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 		*(p++)=sl;
 		memcpy(p,s->session->session_id,sl);
 		p+=sl;
 
 		/* put the cipher */
 		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
 		p+=i;
 
 		/* put the compression method */
 #ifdef OPENSSL_NO_COMP
 			*(p++)=0;
 #else
 		if (s->s3->tmp.new_compression == NULL)
 			*(p++)=0;
 		else
 			*(p++)=s->s3->tmp.new_compression->id;
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 		if (ssl_prepare_serverhello_tlsext(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
 			return -1;
 			}
 		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 #endif
 		/* do the header */
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_SERVER_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_SW_SRVR_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_done(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_SRVR_DONE_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_SRVR_DONE_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	int j,num;
 	RSA *rsa;
 	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	unsigned int u;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL,*dhp;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh=NULL, *ecdhp;
 	unsigned char *encodedPoint = NULL;
 	int encodedlen = 0;
 	int curve_id = 0;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 	EVP_PKEY *pkey;
 	const EVP_MD *md = NULL;
 	unsigned char *p,*d;
 	int al,i;
 	unsigned long type;
 	int n;
 	CERT *cert;
 	BIGNUM *r[4];
 	int nr[4],kn;
 	BUF_MEM *buf;
 	EVP_MD_CTX md_ctx;
 
 	EVP_MD_CTX_init(&md_ctx);
 	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
 		{
 		type=s->s3->tmp.new_cipher->algorithm_mkey;
 		cert=s->cert;
 
 		buf=s->init_buf;
 
 		r[0]=r[1]=r[2]=r[3]=NULL;
 		n=0;
 #ifndef OPENSSL_NO_RSA
 		if (type & SSL_kRSA)
 			{
 			rsa=cert->rsa_tmp;
 			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
 				{
 				rsa=s->cert->rsa_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				if(rsa == NULL)
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
 					goto f_err;
 				}
 				RSA_up_ref(rsa);
 				cert->rsa_tmp=rsa;
 				}
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
 				goto f_err;
 				}
 			r[0]=rsa->n;
 			r[1]=rsa->e;
 			s->s3->tmp.use_rsa_tmp=1;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DH
 			if (type & SSL_kEDH)
 			{
 			dhp=cert->dh_tmp;
 			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
 				dhp=s->cert->dh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 			if (dhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.dh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((dh=DHparams_dup(dhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.dh=dh;
 			if ((dhp->pub_key == NULL ||
 			     dhp->priv_key == NULL ||
 			     (s->options & SSL_OP_SINGLE_DH_USE)))
 				{
 				if(!DH_generate_key(dh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
 					   ERR_R_DH_LIB);
 				    goto err;
 				    }
 				}
 			else
 				{
 				dh->pub_key=BN_dup(dhp->pub_key);
 				dh->priv_key=BN_dup(dhp->priv_key);
 				if ((dh->pub_key == NULL) ||
 					(dh->priv_key == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 					goto err;
 					}
 				}
 			r[0]=dh->p;
 			r[1]=dh->g;
 			r[2]=dh->pub_key;
 			}
 		else 
 #endif
 #ifndef OPENSSL_NO_ECDH
 			if (type & SSL_kEECDH)
 			{
 			const EC_GROUP *group;
 
 			ecdhp=cert->ecdh_tmp;
 			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
 				{
 				ecdhp=s->cert->ecdh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				}
 			if (ecdhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.ecdh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			/* Duplicate the ECDH structure. */
 			if (ecdhp == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.ecdh=ecdh;
 			if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL) ||
 			    (s->options & SSL_OP_SINGLE_ECDH_USE))
 				{
 				if(!EC_KEY_generate_key(ecdh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				    goto err;
 				    }
 				}
 
 			if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
 			    (EC_KEY_get0_public_key(ecdh)  == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 			    (EC_GROUP_get_degree(group) > 163)) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 				goto err;
 				}
 
 			/* XXX: For now, we only support ephemeral ECDH
 			 * keys over named (not generic) curves. For 
 			 * supported named curves, curve_id is non-zero.
 			 */
 			if ((curve_id = 
 			    tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)))
 			    == 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
 				goto err;
 				}
 
 			/* Encode the public key.
 			 * First check the size of encoding and
 			 * allocate memory accordingly.
 			 */
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh),
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    NULL, 0, NULL);
 
 			encodedPoint = (unsigned char *) 
 			    OPENSSL_malloc(encodedlen*sizeof(unsigned char)); 
 			bn_ctx = BN_CTX_new();
 			if ((encodedPoint == NULL) || (bn_ctx == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh), 
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    encodedPoint, encodedlen, bn_ctx);
 
 			if (encodedlen == 0) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			BN_CTX_free(bn_ctx);  bn_ctx=NULL;
 
 			/* XXX: For now, we only support named (not 
 			 * generic) curves in ECDH ephemeral key exchanges.
 			 * In this situation, we need four additional bytes
 			 * to encode the entire ServerECDHParams
 			 * structure. 
 			 */
 			n = 4 + encodedlen;
 
 			/* We'll generate the serverKeyExchange message
 			 * explicitly so we can set these to NULLs
 			 */
 			r[0]=NULL;
 			r[1]=NULL;
 			r[2]=NULL;
 			r[3]=NULL;
 			}
 		else 
 #endif /* !OPENSSL_NO_ECDH */
 #ifndef OPENSSL_NO_PSK
 			if (type & SSL_kPSK)
 				{
 				/* reserve size for record length and PSK identity hint*/
 				n+=2+strlen(s->ctx->psk_identity_hint);
 				}
 			else
 #endif /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
 		if (type & SSL_kSRP)
 			{
 			if ((s->srp_ctx.N == NULL) ||
 				(s->srp_ctx.g == NULL) ||
 				(s->srp_ctx.s == NULL) ||
 				(s->srp_ctx.B == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_SRP_PARAM);
 				goto err;
 				}
 			r[0]=s->srp_ctx.N;
 			r[1]=s->srp_ctx.g;
 			r[2]=s->srp_ctx.s;
 			r[3]=s->srp_ctx.B;
 			}
 		else 
 #endif
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		for (i=0; i < 4 && r[i] != NULL; i++)
 			{
 			nr[i]=BN_num_bytes(r[i]);
 #ifndef OPENSSL_NO_SRP
 			if ((i == 2) && (type & SSL_kSRP))
 				n+=1+nr[i];
 			else
 #endif
 			n+=2+nr[i];
 			}
 
 		if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP))
 			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
 			{
 			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
 				== NULL)
 				{
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			kn=EVP_PKEY_size(pkey);
 			}
 		else
 			{
 			pkey=NULL;
 			kn=0;
 			}
 
 		if (!BUF_MEM_grow_clean(buf,n+4+kn))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
 			goto err;
 			}
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		for (i=0; i < 4 && r[i] != NULL; i++)
 			{
 #ifndef OPENSSL_NO_SRP
 			if ((i == 2) && (type & SSL_kSRP))
 				{
 				*p = nr[i];
 				p++;
 				}
 			else
 #endif
 			s2n(nr[i],p);
 			BN_bn2bin(r[i],p);
 			p+=nr[i];
 			}
 
 #ifndef OPENSSL_NO_ECDH
 		if (type & SSL_kEECDH) 
 			{
 			/* XXX: For now, we only support named (not generic) curves.
 			 * In this situation, the serverKeyExchange message has:
 			 * [1 byte CurveType], [2 byte CurveName]
 			 * [1 byte length of encoded point], followed by
 			 * the actual encoded point itself
 			 */
 			*p = NAMED_CURVE_TYPE;
 			p += 1;
 			*p = 0;
 			p += 1;
 			*p = curve_id;
 			p += 1;
 			*p = encodedlen;
 			p += 1;
 			memcpy((unsigned char*)p, 
 			    (unsigned char *)encodedPoint, 
 			    encodedlen);
 			OPENSSL_free(encodedPoint);
 			encodedPoint = NULL;
 			p += encodedlen;
 			}
 #endif
 
 #ifndef OPENSSL_NO_PSK
 		if (type & SSL_kPSK)
 			{
 			/* copy PSK identity hint */
 			s2n(strlen(s->ctx->psk_identity_hint), p); 
 			strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
 			p+=strlen(s->ctx->psk_identity_hint);
 			}
 #endif
 
 		/* not anonymous */
 		if (pkey != NULL)
 			{
 			/* n is the length of the params, they start at &(d[4])
 			 * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
 			if (pkey->type == EVP_PKEY_RSA
 					&& TLS1_get_version(s) < TLS1_2_VERSION)
 				{
 				q=md_buf;
 				j=0;
 				for (num=2; num > 0; num--)
 					{
 					EVP_MD_CTX_set_flags(&md_ctx,
 						EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 					EVP_DigestInit_ex(&md_ctx,(num == 2)
 						?s->ctx->md5:s->ctx->sha1, NULL);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(d[4]),n);
 					EVP_DigestFinal_ex(&md_ctx,q,
 						(unsigned int *)&i);
 					q+=i;
 					j+=i;
 					}
 				if (RSA_sign(NID_md5_sha1, md_buf, j,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0)
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
 					goto err;
 					}
 				s2n(u,p);
 				n+=u+2;
 				}
 			else
 #endif
 			if (md)
 				{
 				/* For TLS1.2 and later send signature
 				 * algorithm */
 				if (TLS1_get_version(s) >= TLS1_2_VERSION)
 					{
 					if (!tls12_get_sigandhash(p, pkey, md))
 						{
 						/* Should never happen */
 						al=SSL_AD_INTERNAL_ERROR;
 						SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 						goto f_err;
 						}
 					p+=2;
 					}
 #ifdef SSL_DEBUG
 				fprintf(stderr, "Using hash %s\n",
 							EVP_MD_name(md));
 #endif
 				EVP_SignInit_ex(&md_ctx, md, NULL);
 				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(d[4]),n);
 				if (!EVP_SignFinal(&md_ctx,&(p[2]),
 					(unsigned int *)&i,pkey))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_EVP);
 					goto err;
 					}
 				s2n(i,p);
 				n+=i+2;
 				if (TLS1_get_version(s) >= TLS1_2_VERSION)
 					n+= 2;
 				}
 			else
 				{
 				/* Is this error check actually needed? */
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
 				goto f_err;
 				}
 			}
 
 		*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	s->state = SSL3_ST_SW_KEY_EXCH_B;
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 #ifndef OPENSSL_NO_ECDH
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	BN_CTX_free(bn_ctx);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_send_certificate_request(SSL *s)
 	{
 	unsigned char *p,*d;
 	int i,j,nl,off,n;
 	STACK_OF(X509_NAME) *sk=NULL;
 	X509_NAME *name;
 	BUF_MEM *buf;
 
 	if (s->state == SSL3_ST_SW_CERT_REQ_A)
 		{
 		buf=s->init_buf;
 
 		d=p=(unsigned char *)&(buf->data[4]);
 
 		/* get the list of acceptable cert types */
 		p++;
 		n=ssl3_get_req_cert_type(s,p);
 		d[0]=n;
 		p+=n;
 		n++;
 
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
 			nl = tls12_get_req_sig_algs(s, p + 2);
 			s2n(nl, p);
 			p += nl + 2;
 			n += nl + 2;
 			}
 
 		off=n;
 		p+=2;
 		n+=2;
 
 		sk=SSL_get_client_CA_list(s);
 		nl=0;
 		if (sk != NULL)
 			{
 			for (i=0; idata[4+n]);
 				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 					{
 					s2n(j,p);
 					i2d_X509_NAME(name,&p);
 					n+=2+j;
 					nl+=2+j;
 					}
 				else
 					{
 					d=p;
 					i2d_X509_NAME(name,&p);
 					j-=2; s2n(j,d); j+=2;
 					n+=j;
 					nl+=j;
 					}
 				}
 			}
 		/* else no CA names */
 		p=(unsigned char *)&(buf->data[4+off]);
 		s2n(nl,p);
 
 		d=(unsigned char *)buf->data;
 		*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 
 		s->init_num=n+4;
 		s->init_off=0;
 #ifdef NETSCAPE_HANG_BUG
 		if (!BUF_MEM_grow_clean(buf, s->init_num + 4))
 			{
 			SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
 			goto err;
 			}
 		p=(unsigned char *)s->init_buf->data + s->init_num;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 		s->init_num += 4;
 #endif
 
 		s->state = SSL3_ST_SW_CERT_REQ_B;
 		}
 
 	/* SSL3_ST_SW_CERT_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_client_key_exchange(SSL *s)
 	{
 	int i,al,ok;
 	long n;
 	unsigned long alg_k;
 	unsigned char *p;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	BIGNUM *pub=NULL;
 	DH *dh_srvr;
 #endif
 #ifndef OPENSSL_NO_KRB5
 	KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *srvr_ecdh = NULL;
 	EVP_PKEY *clnt_pub_pkey = NULL;
 	EC_POINT *clnt_ecpoint = NULL;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_KEY_EXCH_A,
 		SSL3_ST_SR_KEY_EXCH_B,
 		SSL3_MT_CLIENT_KEY_EXCHANGE,
 		2048, /* ??? */
 		&ok);
 
 	if (!ok) return((int)n);
 	p=(unsigned char *)s->init_msg;
 
 	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 
 #ifndef OPENSSL_NO_RSA
 	if (alg_k & SSL_kRSA)
 		{
 		unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
 		int decrypt_len;
 		unsigned char decrypt_good, version_good;
 		size_t j;
 
 		/* FIX THIS UP EAY EAY EAY EAY */
 		if (s->s3->tmp.use_rsa_tmp)
 			{
 			if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
 				rsa=s->cert->rsa_tmp;
 			/* Don't do a callback because rsa_tmp should
 			 * be sent already */
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY);
 				goto f_err;
 
 				}
 			}
 		else
 			{
 			pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
 			if (	(pkey == NULL) ||
 				(pkey->type != EVP_PKEY_RSA) ||
 				(pkey->pkey.rsa == NULL))
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
 				goto f_err;
 				}
 			rsa=pkey->pkey.rsa;
 			}
 
 		/* TLS and [incidentally] DTLS{0xFEFF} */
 		if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
 			{
 			n2s(p,i);
 			if (n != i+2)
 				{
 				if (!(s->options & SSL_OP_TLS_D5_BUG))
 					{
 					al = SSL_AD_DECODE_ERROR;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
 					goto f_err;
 					}
 				else
 					p-=2;
 				}
 			else
 				n=i;
 			}
 
 		/*
 		 * Reject overly short RSA ciphertext because we want to be sure
 		 * that the buffer size makes it safe to iterate over the entire
 		 * size of a premaster secret (SSL_MAX_MASTER_KEY_LENGTH). The
 		 * actual expected size is larger due to RSA padding, but the
 		 * bound is sufficient to be safe.
 		 */
 		if (n < SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			al = SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
 			goto f_err;
 			}
 
 		/* We must not leak whether a decryption failure occurs because
 		 * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see
 		 * RFC 2246, section 7.4.7.1). The code follows that advice of
 		 * the TLS RFC and generates a random premaster secret for the
 		 * case that the decrypt fails. See
 		 * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */
 
 		/* should be RAND_bytes, but we cannot work around a failure. */
 		if (RAND_pseudo_bytes(rand_premaster_secret,
 				      sizeof(rand_premaster_secret)) <= 0)
 			goto err;
 		decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
 		ERR_clear_error();
 
 		/* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
 		 * decrypt_good will be 0xff if so and zero otherwise. */
 		decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
 
 		/* If the version in the decrypted pre-master secret is correct
 		 * then version_good will be 0xff, otherwise it'll be zero.
 		 * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
 		 * (http://eprint.iacr.org/2003/052/) exploits the version
 		 * number check as a "bad version oracle". Thus version checks
 		 * are done in constant time and are treated like any other
 		 * decryption error. */
 		version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
 		version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
 
 		/* The premaster secret must contain the same version number as
 		 * the ClientHello to detect version rollback attacks
 		 * (strangely, the protocol does not offer such protection for
 		 * DH ciphersuites). However, buggy clients exist that send the
 		 * negotiated protocol version instead if the server does not
 		 * support the requested protocol version. If
 		 * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
 		if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
 			{
 			unsigned char workaround_good;
 			workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
 			workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
 			version_good |= workaround_good;
 			}
 
 		/* Both decryption and version must be good for decrypt_good
 		 * to remain non-zero (0xff). */
 		decrypt_good &= version_good;
 
 		/*
 		 * Now copy rand_premaster_secret over from p using
 		 * decrypt_good_mask. If decryption failed, then p does not
 		 * contain valid plaintext, however, a check above guarantees
 		 * it is still sufficiently large to read from.
 		 */
 		for (j = 0; j < sizeof(rand_premaster_secret); j++)
 			{
 			p[j] = constant_time_select_8(decrypt_good, p[j],
 						      rand_premaster_secret[j]);
 			}
 
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,
 				p,sizeof(rand_premaster_secret));
 		OPENSSL_cleanse(p,sizeof(rand_premaster_secret));
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DH
 		if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 		{
 		n2s(p,i);
 		if (n != i+2)
 			{
 			if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
 				goto err;
 				}
 			else
 				{
 				p-=2;
 				i=(int)n;
 				}
 			}
 
 		if (n == 0L) /* the parameters are in the cert */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
 			goto f_err;
 			}
 		else
 			{
 			if (s->s3->tmp.dh == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 			else
 				dh_srvr=s->s3->tmp.dh;
 			}
 
 		pub=BN_bin2bn(p,i,NULL);
 		if (pub == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB);
 			goto err;
 			}
 
 		i=DH_compute_key(p,pub,dh_srvr);
 
 		if (i <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 			BN_clear_free(pub);
 			goto err;
 			}
 
 		DH_free(s->s3->tmp.dh);
 		s->s3->tmp.dh=NULL;
 
 		BN_clear_free(pub);
 		pub=NULL;
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,p,i);
 		OPENSSL_cleanse(p,i);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_KRB5
 	if (alg_k & SSL_kKRB5)
 		{
 		krb5_error_code		krb5rc;
 		krb5_data		enc_ticket;
 		krb5_data		authenticator;
 		krb5_data		enc_pms;
 		KSSL_CTX		*kssl_ctx = s->kssl_ctx;
 		EVP_CIPHER_CTX		ciph_ctx;
 		const EVP_CIPHER	*enc = NULL;
 		unsigned char		iv[EVP_MAX_IV_LENGTH];
 		unsigned char		pms[SSL_MAX_MASTER_KEY_LENGTH
 					       + EVP_MAX_BLOCK_LENGTH];
 		int		     padl, outl;
 		krb5_timestamp		authtime = 0;
 		krb5_ticket_times	ttimes;
+        int kerr = 0;
 
 		EVP_CIPHER_CTX_init(&ciph_ctx);
 
 		if (!kssl_ctx)  kssl_ctx = kssl_ctx_new();
 
 		n2s(p,i);
 		enc_ticket.length = i;
 
 		if (n < (long)(enc_ticket.length + 6))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		enc_ticket.data = (char *)p;
 		p+=enc_ticket.length;
 
 		n2s(p,i);
 		authenticator.length = i;
 
 		if (n < (long)(enc_ticket.length + authenticator.length + 6))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		authenticator.data = (char *)p;
 		p+=authenticator.length;
 
 		n2s(p,i);
 		enc_pms.length = i;
 		enc_pms.data = (char *)p;
 		p+=enc_pms.length;
 
 		/* Note that the length is checked again below,
 		** after decryption
 		*/
 		if(enc_pms.length > sizeof pms)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		if (n != (long)(enc_ticket.length + authenticator.length +
 						enc_pms.length + 6))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
 					&kssl_err)) != 0)
 			{
 #ifdef KSSL_DEBUG
 			fprintf(stderr,"kssl_sget_tkt rtn %d [%d]\n",
 				krb5rc, kssl_err.reason);
 			if (kssl_err.text)
 				fprintf(stderr,"kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				kssl_err.reason);
 			goto err;
 			}
 
 		/*  Note: no authenticator is not considered an error,
 		**  but will return authtime == 0.
 		*/
 		if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
 					&authtime, &kssl_err)) != 0)
 			{
 #ifdef KSSL_DEBUG
 			fprintf(stderr,"kssl_check_authent rtn %d [%d]\n",
 				krb5rc, kssl_err.reason);
 			if (kssl_err.text)
 				fprintf(stderr,"kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				kssl_err.reason);
 			goto err;
 			}
 
 		if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
 			goto err;
 			}
 
 #ifdef KSSL_DEBUG
 		kssl_ctx_show(kssl_ctx);
 #endif	/* KSSL_DEBUG */
 
 		enc = kssl_map_enc(kssl_ctx->enctype);
 		if (enc == NULL)
 		    goto err;
 
 		memset(iv, 0, sizeof iv);	/* per RFC 1510 */
 
 		if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
 			goto err;
 			}
 		if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
 					(unsigned char *)enc_pms.data, enc_pms.length))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		outl += padl;
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
 		    {
 		    /* The premaster secret must contain the same version number as the
 		     * ClientHello to detect version rollback attacks (strangely, the
 		     * protocol does not offer such protection for DH ciphersuites).
 		     * However, buggy clients exist that send random bytes instead of
 		     * the protocol version.
 		     * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. 
 		     * (Perhaps we should have a separate BUG value for the Kerberos cipher)
 		     */
 		    if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_AD_DECODE_ERROR);
-			goto err;
+                kerr = 1;
+                goto kclean;
 			}
 		    }
 
 		EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key, pms, outl);
 
 		if (kssl_ctx->client_princ)
 			{
 			size_t len = strlen(kssl_ctx->client_princ);
 			if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) 
 				{
 				s->session->krb5_client_princ_len = len;
 				memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
 				}
 			}
 
 
 		/*  Was doing kssl_ctx_free() here,
 		**  but it caused problems for apache.
 		**  kssl_ctx = kssl_ctx_free(kssl_ctx);
 		**  if (s->kssl_ctx)  s->kssl_ctx = NULL;
 		*/
+
+ kclean:
+        OPENSSL_cleanse(pms, sizeof(pms));
+        if (kerr)
+            goto err;
 		}
 	else
 #endif	/* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 		if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
 		{
 		int ret = 1;
 		int field_size = 0;
 		const EC_KEY   *tkey;
 		const EC_GROUP *group;
 		const BIGNUM *priv_key;
 
 		/* initialize structures for server's ECDH key pair */
 		if ((srvr_ecdh = EC_KEY_new()) == NULL) 
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		/* Let's get server private key and group information */
 		if (alg_k & (SSL_kECDHr|SSL_kECDHe))
 			{ 
 			/* use the certificate */
 			tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
 			}
 		else
 			{
 			/* use the ephermeral values we saved when
 			 * generating the ServerKeyExchange msg.
 			 */
 			tkey = s->s3->tmp.ecdh;
 			}
 
 		group    = EC_KEY_get0_group(tkey);
 		priv_key = EC_KEY_get0_private_key(tkey);
 
 		if (!EC_KEY_set_group(srvr_ecdh, group) ||
 		    !EC_KEY_set_private_key(srvr_ecdh, priv_key))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       ERR_R_EC_LIB);
 			goto err;
 			}
 
 		/* Let's get client's public key */
 		if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		if (n == 0L) 
 			{
 			/* Client Publickey was in Client Certificate */
 
 			 if (alg_k & SSL_kEECDH)
 				 {
 				 al=SSL_AD_HANDSHAKE_FAILURE;
 				 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				 goto f_err;
 				 }
 			if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
 			    == NULL) || 
 			    (clnt_pub_pkey->type != EVP_PKEY_EC))
 				{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates
 				 * so this branch (n == 0L) of the code is
 				 * never executed. When that support is
 				 * added, we ought to ensure the key 
 				 * received in the certificate is 
 				 * authorized for key agreement.
 				 * ECDH_compute_key implicitly checks that
 				 * the two ECDH shares are for the same
 				 * group.
 				 */
 			   	al=SSL_AD_HANDSHAKE_FAILURE;
 			   	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
 			   	goto f_err;
 			   	}
 
 			if (EC_POINT_copy(clnt_ecpoint,
 			    EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_EC_LIB);
 				goto err;
 				}
 			ret = 2; /* Skip certificate verify processing */
 			}
 		else
 			{
 			/* Get client's public key from encoded point
 			 * in the ClientKeyExchange message.
 			 */
 			if ((bn_ctx = BN_CTX_new()) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			/* Get encoded point length */
 			i = *p; 
 			p += 1;
 			if (n != 1 + i)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
 			if (EC_POINT_oct2point(group, 
 			    clnt_ecpoint, p, i, bn_ctx) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
 			/* p is pointing to somewhere in the buffer
 			 * currently, so set it to the start 
 			 */ 
 			p=(unsigned char *)s->init_buf->data;
 			}
 
 		/* Compute the shared pre-master secret */
 		field_size = EC_GROUP_get_degree(group);
 		if (field_size <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, 
 			       ERR_R_ECDH_LIB);
 			goto err;
 			}
 		i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
 		if (i <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_ECDH_LIB);
 			goto err;
 			}
 
 		EVP_PKEY_free(clnt_pub_pkey);
 		EC_POINT_free(clnt_ecpoint);
 		EC_KEY_free(srvr_ecdh);
 		BN_CTX_free(bn_ctx);
 		EC_KEY_free(s->s3->tmp.ecdh);
 		s->s3->tmp.ecdh = NULL; 
 
 		/* Compute the master secret */
 		s->session->master_key_length = s->method->ssl3_enc-> \
 		    generate_master_secret(s, s->session->master_key, p, i);
 		
 		OPENSSL_cleanse(p, i);
 		return (ret);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_PSK
 		if (alg_k & SSL_kPSK)
 			{
 			unsigned char *t = NULL;
 			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
 			unsigned int pre_ms_len = 0, psk_len = 0;
 			int psk_err = 1;
 			char tmp_id[PSK_MAX_IDENTITY_LEN+1];
 
 			al=SSL_AD_HANDSHAKE_FAILURE;
 
 			n2s(p,i);
 			if (n != i+2)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					SSL_R_LENGTH_MISMATCH);
 				goto psk_err;
 				}
 			if (i > PSK_MAX_IDENTITY_LEN)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					SSL_R_DATA_LENGTH_TOO_LONG);
 				goto psk_err;
 				}
 			if (s->psk_server_callback == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				       SSL_R_PSK_NO_SERVER_CB);
 				goto psk_err;
 				}
 
 			/* Create guaranteed NULL-terminated identity
 			 * string for the callback */
 			memcpy(tmp_id, p, i);
 			memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
 			psk_len = s->psk_server_callback(s, tmp_id,
 				psk_or_pre_ms, sizeof(psk_or_pre_ms));
 			OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
 
 			if (psk_len > PSK_MAX_PSK_LEN)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_INTERNAL_ERROR);
 				goto psk_err;
 				}
 			else if (psk_len == 0)
 				{
 				/* PSK related to the given identity not found */
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				       SSL_R_PSK_IDENTITY_NOT_FOUND);
 				al=SSL_AD_UNKNOWN_PSK_IDENTITY;
 				goto psk_err;
 				}
 
 			/* create PSK pre_master_secret */
 			pre_ms_len=2+psk_len+2+psk_len;
 			t = psk_or_pre_ms;
 			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
 			s2n(psk_len, t);
 			memset(t, 0, psk_len);
 			t+=psk_len;
 			s2n(psk_len, t);
 
 			if (s->session->psk_identity != NULL)
 				OPENSSL_free(s->session->psk_identity);
 			s->session->psk_identity = BUF_strdup((char *)p);
 			if (s->session->psk_identity == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto psk_err;
 				}
 
 			if (s->session->psk_identity_hint != NULL)
 				OPENSSL_free(s->session->psk_identity_hint);
 			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
 			if (s->ctx->psk_identity_hint != NULL &&
 				s->session->psk_identity_hint == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto psk_err;
 				}
 
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key, psk_or_pre_ms, pre_ms_len);
 			psk_err = 0;
 		psk_err:
 			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
 			if (psk_err != 0)
 				goto f_err;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_SRP
 		if (alg_k & SSL_kSRP)
 			{
 			int param_len;
 
 			n2s(p,i);
 			param_len=i+2;
 			if (param_len > n)
 				{
 				al=SSL_AD_DECODE_ERROR;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
 				goto f_err;
 				}
 			if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
 				goto err;
 				}
 			if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0
 				|| BN_is_zero(s->srp_ctx.A))
 				{
 				al=SSL_AD_ILLEGAL_PARAMETER;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
 				goto f_err;
 				}
 			if (s->session->srp_username != NULL)
 				OPENSSL_free(s->session->srp_username);
 			s->session->srp_username = BUF_strdup(s->srp_ctx.login);
 			if (s->session->srp_username == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			p+=i;
 			}
 		else
 #endif	/* OPENSSL_NO_SRP */
 		if (alg_k & SSL_kGOST) 
 			{
 			int ret = 0;
 			EVP_PKEY_CTX *pkey_ctx;
 			EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
 			unsigned char premaster_secret[32], *start;
 			size_t outlen=32, inlen;
 			unsigned long alg_a;
 			int Ttag, Tclass;
 			long Tlen;
 
 			/* Get our certificate private key*/
 			alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 			if (alg_a & SSL_aGOST94)
 				pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
 			else if (alg_a & SSL_aGOST01)
 				pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
 
 			pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
 			EVP_PKEY_decrypt_init(pkey_ctx);
 			/* If client certificate is present and is of the same type, maybe
 			 * use it for key exchange.  Don't mind errors from
 			 * EVP_PKEY_derive_set_peer, because it is completely valid to use
 			 * a client certificate for authorization only. */
 			client_pub_pkey = X509_get_pubkey(s->session->peer);
 			if (client_pub_pkey)
 				{
 				if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
 					ERR_clear_error();
 				}
 			/* Decrypt session key */
 			if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED || 
 				Ttag != V_ASN1_SEQUENCE ||
 			 	Tclass != V_ASN1_UNIVERSAL) 
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
 				goto gerr;
 				}
 			start = p;
 			inlen = Tlen;
 			if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0) 
 
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
 				goto gerr;
 				}
 			/* Generate master secret */
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,premaster_secret,32);
 			/* Check if pubkey from client certificate was used */
 			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
 				ret = 2;
 			else
 				ret = 1;
 		gerr:
 			EVP_PKEY_free(client_pub_pkey);
 			EVP_PKEY_CTX_free(pkey_ctx);
 			if (ret)
 				return ret;
 			else
 				goto err;
 			}
 		else
 		{
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_UNKNOWN_CIPHER_TYPE);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) || defined(OPENSSL_NO_SRP)
 err:
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EVP_PKEY_free(clnt_pub_pkey);
 	EC_POINT_free(clnt_ecpoint);
 	if (srvr_ecdh != NULL) 
 		EC_KEY_free(srvr_ecdh);
 	BN_CTX_free(bn_ctx);
 #endif
 	return(-1);
 	}
 
 int ssl3_get_cert_verify(SSL *s)
 	{
 	EVP_PKEY *pkey=NULL;
 	unsigned char *p;
 	int al,ok,ret=0;
 	long n;
 	int type=0,i,j;
 	X509 *peer;
 	const EVP_MD *md = NULL;
 	EVP_MD_CTX mctx;
 	EVP_MD_CTX_init(&mctx);
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_VRFY_A,
 		SSL3_ST_SR_CERT_VRFY_B,
 		-1,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if (s->session->peer != NULL)
 		{
 		peer=s->session->peer;
 		pkey=X509_get_pubkey(peer);
 		type=X509_certificate_type(peer,pkey);
 		}
 	else
 		{
 		peer=NULL;
 		pkey=NULL;
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
 		{
 		s->s3->tmp.reuse_message=1;
 		if (peer != NULL)
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
 			goto f_err;
 			}
 		ret=1;
 		goto end;
 		}
 
 	if (peer == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	if (!(type & EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		goto f_err;
 		}
 
 	if (s->s3->change_cipher_spec)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	/* we now have a signature that we need to verify */
 	p=(unsigned char *)s->init_msg;
 	/* Check for broken implementations of GOST ciphersuites */
 	/* If key is GOST and n is exactly 64, it is bare
 	 * signature without length field */
 	if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
 		pkey->type == NID_id_GostR3410_2001) )
 		{
 		i=64;
 		} 
 	else 
 		{	
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
 			int sigalg = tls12_get_sigid(pkey);
 			/* Should never happen */
 			if (sigalg == -1)
 				{
 				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
 				al=SSL_AD_INTERNAL_ERROR;
 				goto f_err;
 				}
 			/* Check key type is consistent with signature */
 			if (sigalg != (int)p[1])
 				{
 				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			md = tls12_get_hash(p[0]);
 			if (md == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 #ifdef SSL_DEBUG
 fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
 			p += 2;
 			n -= 2;
 			}
 		n2s(p,i);
 		n-=2;
 		if (i > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
 			al=SSL_AD_DECODE_ERROR;
 			goto f_err;
 			}
     	}
 	j=EVP_PKEY_size(pkey);
 	if ((i > j) || (n > j) || (n <= 0))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
 		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
 	if (TLS1_get_version(s) >= TLS1_2_VERSION)
 		{
 		long hdatalen = 0;
 		void *hdata;
 		hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
 		if (hdatalen <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
 			al=SSL_AD_INTERNAL_ERROR;
 			goto f_err;
 			}
 #ifdef SSL_DEBUG
 		fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
 							EVP_MD_name(md));
 #endif
 		if (!EVP_VerifyInit_ex(&mctx, md, NULL)
 			|| !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
 			{
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
 			al=SSL_AD_INTERNAL_ERROR;
 			goto f_err;
 			}
 
 		if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #ifndef OPENSSL_NO_RSA 
 	if (pkey->type == EVP_PKEY_RSA)
 		{
 		i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
 			MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, 
 							pkey->pkey.rsa);
 		if (i < 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
 			goto f_err;
 			}
 		if (i == 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DSA
 		if (pkey->type == EVP_PKEY_DSA)
 		{
 		j=DSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		if (pkey->type == EVP_PKEY_EC)
 		{
 		j=ECDSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
 			    SSL_R_BAD_ECDSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 	if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
 		{   unsigned char signature[64];
 			int idx;
 			EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
 			EVP_PKEY_verify_init(pctx);
 			if (i!=64) {
 				fprintf(stderr,"GOST signature length is %d",i);
 			}	
 			for (idx=0;idx<64;idx++) {
 				signature[63-idx]=p[idx];
 			}	
 			j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
 			EVP_PKEY_CTX_free(pctx);
 			if (j<=0) 
 				{
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
 					SSL_R_BAD_ECDSA_SIGNATURE);
 				goto f_err;
 				}	
 		}
 	else	
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
 		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
 		goto f_err;
 		}
 
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 end:
 	if (s->s3->handshake_buffer)
 		{
 		BIO_free(s->s3->handshake_buffer);
 		s->s3->handshake_buffer = NULL;
 		s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
 		}
 	EVP_MD_CTX_cleanup(&mctx);
 	EVP_PKEY_free(pkey);
 	return(ret);
 	}
 
 int ssl3_get_client_certificate(SSL *s)
 	{
 	int i,ok,al,ret= -1;
 	X509 *x=NULL;
 	unsigned long l,nc,llen,n;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if	(s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
 		{
 		if (	(s->verify_mode & SSL_VERIFY_PEER) &&
 			(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		/* If tls asked for a client cert, the client must return a 0 list */
 		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&p,l);
 		if (x == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto err;
 			}
 		if (p != (q+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		}
 
 	if (sk_X509_num(sk) <= 0)
 		{
 		/* TLS does not mind 0 certs returned */
 		if (s->version == SSL3_VERSION)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
 			goto f_err;
 			}
 		/* Fail for TLS only if we required a certificate */
 		else if ((s->verify_mode & SSL_VERIFY_PEER) &&
 			 (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		/* No client certificate so digest cached records */
 		if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			goto f_err;
 			}
 		}
 	else
 		{
 		i=ssl_verify_cert_chain(s,sk);
 		if (i <= 0)
 			{
 			al=ssl_verify_alarm_type(s->verify_result);
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
 			goto f_err;
 			}
 		}
 
 	if (s->session->peer != NULL) /* This should not be needed */
 		X509_free(s->session->peer);
 	s->session->peer=sk_X509_shift(sk);
 	s->session->verify_result = s->verify_result;
 
 	/* With the current implementation, sess_cert will always be NULL
 	 * when we arrive here. */
 	if (s->session->sess_cert == NULL)
 		{
 		s->session->sess_cert = ssl_sess_cert_new();
 		if (s->session->sess_cert == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	if (s->session->sess_cert->cert_chain != NULL)
 		sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
 	s->session->sess_cert->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does *not* include the
 	 * peer's own certificate, while we do include it in s3_clnt.c */
 
 	sk=NULL;
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (x != NULL) X509_free(x);
 	if (sk != NULL) sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_send_server_certificate(SSL *s)
 	{
 	unsigned long l;
 	X509 *x;
 
 	if (s->state == SSL3_ST_SW_CERT_A)
 		{
 		x=ssl_get_server_send_cert(s);
 		if (x == NULL)
 			{
 			/* VRS: allow null cert if auth == KRB5 */
 			if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
 			    (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
 				return(0);
 				}
 			}
 
 		l=ssl3_output_cert_chain(s,x);
 		if (!l)
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
 			return(0);
 			}
 		s->state=SSL3_ST_SW_CERT_B;
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_CERT_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 #ifndef OPENSSL_NO_TLSEXT
 /* send a new session ticket (not necessarily for a new session) */
 int ssl3_send_newsession_ticket(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
 		{
 		unsigned char *p, *senc, *macstart;
 		const unsigned char *const_p;
 		int len, slen_full, slen;
 		SSL_SESSION *sess;
 		unsigned int hlen;
 		EVP_CIPHER_CTX ctx;
 		HMAC_CTX hctx;
 		SSL_CTX *tctx = s->initial_ctx;
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char key_name[16];
 
 		/* get session encoding length */
 		slen_full = i2d_SSL_SESSION(s->session, NULL);
 		/* Some length values are 16 bits, so forget it if session is
  		 * too long
  		 */
 		if (slen_full > 0xFF00)
 			return -1;
 		senc = OPENSSL_malloc(slen_full);
 		if (!senc)
 			return -1;
 		p = senc;
 		i2d_SSL_SESSION(s->session, &p);
 
 		/* create a fresh copy (not shared with other threads) to clean up */
 		const_p = senc;
 		sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
 		if (sess == NULL)
 			{
 			OPENSSL_free(senc);
 			return -1;
 			}
 		sess->session_id_length = 0; /* ID is irrelevant for the ticket */
 
 		slen = i2d_SSL_SESSION(sess, NULL);
 		if (slen > slen_full) /* shouldn't ever happen */
 			{
 			OPENSSL_free(senc);
 			return -1;
 			}
 		p = senc;
 		i2d_SSL_SESSION(sess, &p);
 		SSL_SESSION_free(sess);
 
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (size of message name) + 3 (message length
  		 * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
  		 * 16 (key name) + max_iv_len (iv length) +
  		 * session_length + max_enc_block_size (max encrypted session
  		 * length) + max_md_size (HMAC).
  		 */
 		if (!BUF_MEM_grow(s->init_buf,
 			26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
 			EVP_MAX_MD_SIZE + slen))
 			return -1;
 
 		p=(unsigned char *)s->init_buf->data;
 		/* do the header */
 		*(p++)=SSL3_MT_NEWSESSION_TICKET;
 		/* Skip message length for now */
 		p += 3;
 		EVP_CIPHER_CTX_init(&ctx);
 		HMAC_CTX_init(&hctx);
 		/* Initialize HMAC and cipher contexts. If callback present
 		 * it does all the work otherwise use generated values
 		 * from parent ctx.
 		 */
 		if (tctx->tlsext_ticket_key_cb)
 			{
 			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
 							 &hctx, 1) < 0)
 				{
 				OPENSSL_free(senc);
 				return -1;
 				}
 			}
 		else
 			{
 			RAND_pseudo_bytes(iv, 16);
 			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
 					tctx->tlsext_tick_aes_key, iv);
 			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
 					tlsext_tick_md(), NULL);
 			memcpy(key_name, tctx->tlsext_tick_key_name, 16);
 			}
 
 		/* Ticket lifetime hint (advisory only):
 		 * We leave this unspecified for resumed session (for simplicity),
 		 * and guess that tickets for new sessions will live as long
 		 * as their sessions. */
 		l2n(s->hit ? 0 : s->session->timeout, p);
 
 		/* Skip ticket length for now */
 		p += 2;
 		/* Output key name */
 		macstart = p;
 		memcpy(p, key_name, 16);
 		p += 16;
 		/* output IV */
 		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
 		p += EVP_CIPHER_CTX_iv_length(&ctx);
 		/* Encrypt session data */
 		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
 		p += len;
 		EVP_EncryptFinal(&ctx, p, &len);
 		p += len;
 		EVP_CIPHER_CTX_cleanup(&ctx);
 
 		HMAC_Update(&hctx, macstart, p - macstart);
 		HMAC_Final(&hctx, p, &hlen);
 		HMAC_CTX_cleanup(&hctx);
 
 		p += hlen;
 		/* Now write out lengths: p points to end of data written */
 		/* Total length */
 		len = p - (unsigned char *)s->init_buf->data;
 		p=(unsigned char *)s->init_buf->data + 1;
 		l2n3(len - 4, p); /* Message length */
 		p += 4;
 		s2n(len - 10, p);  /* Ticket length */
 
 		/* number of bytes to write */
 		s->init_num= len;
 		s->state=SSL3_ST_SW_SESSION_TICKET_B;
 		s->init_off=0;
 		OPENSSL_free(senc);
 		}
 
 	/* SSL3_ST_SW_SESSION_TICKET_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_cert_status(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_CERT_STATUS_A)
 		{
 		unsigned char *p;
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (message type) + 3 (message length) +
  		 * 1 (ocsp response type) + 3 (ocsp response length)
  		 * + (ocsp response)
  		 */
 		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
 			return -1;
 
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_CERTIFICATE_STATUS;
 		/* message length */
 		l2n3(s->tlsext_ocsp_resplen + 4, p);
 		/* status type */
 		*(p++)= s->tlsext_status_type;
 		/* length of OCSP response */
 		l2n3(s->tlsext_ocsp_resplen, p);
 		/* actual response */
 		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
 		/* number of bytes to write */
 		s->init_num = 8 + s->tlsext_ocsp_resplen;
 		s->state=SSL3_ST_SW_CERT_STATUS_B;
 		s->init_off = 0;
 		}
 
 	/* SSL3_ST_SW_CERT_STATUS_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 # ifndef OPENSSL_NO_NEXTPROTONEG
 /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
  * sets the next_proto member in s if found */
 int ssl3_get_next_proto(SSL *s)
 	{
 	int ok;
 	int proto_len, padding_len;
 	long n;
 	const unsigned char *p;
 
 	/* Clients cannot send a NextProtocol message if we didn't see the
 	 * extension in their ClientHello */
 	if (!s->s3->next_proto_neg_seen)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
 		return -1;
 		}
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_NEXT_PROTO_A,
 		SSL3_ST_SR_NEXT_PROTO_B,
 		SSL3_MT_NEXT_PROTO,
 		514,  /* See the payload format below */
 		&ok);
 
 	if (!ok)
 		return((int)n);
 
 	/* s->state doesn't reflect whether ChangeCipherSpec has been received
 	 * in this handshake, but s->s3->change_cipher_spec does (will be reset
 	 * by ssl3_get_finished). */
 	if (!s->s3->change_cipher_spec)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
 		return -1;
 		}
 
 	if (n < 2)
 		return 0;  /* The body must be > 1 bytes long */
 
 	p=(unsigned char *)s->init_msg;
 
 	/* The payload looks like:
 	 *   uint8 proto_len;
 	 *   uint8 proto[proto_len];
 	 *   uint8 padding_len;
 	 *   uint8 padding[padding_len];
 	 */
 	proto_len = p[0];
 	if (proto_len + 2 > s->init_num)
 		return 0;
 	padding_len = p[proto_len + 1];
 	if (proto_len + padding_len + 2 != s->init_num)
 		return 0;
 
 	s->next_proto_negotiated = OPENSSL_malloc(proto_len);
 	if (!s->next_proto_negotiated)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	memcpy(s->next_proto_negotiated, p + 1, proto_len);
 	s->next_proto_negotiated_len = proto_len;
 
 	return 1;
 	}
 # endif
 #endif
Index: releng/10.1/crypto/openssl/ssl/ssl.h
===================================================================
--- releng/10.1/crypto/openssl/ssl/ssl.h	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/ssl.h	(revision 284295)
@@ -1,2617 +1,2619 @@
 /* ssl/ssl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 /* ====================================================================
  * Copyright 2005 Nokia. All rights reserved.
  *
  * The portions of the attached software ("Contribution") is developed by
  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
  * license.
  *
  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
  * support (see RFC 4279) to OpenSSL.
  *
  * No patent licenses or other rights except those expressly stated in
  * the OpenSSL open source license shall be deemed granted or received
  * expressly, by implication, estoppel, or otherwise.
  *
  * No assurances are provided by Nokia that the Contribution does not
  * infringe the patent or other intellectual property rights of any third
  * party or that the license provides you with all the necessary rights
  * to make use of the Contribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
 
 #ifndef HEADER_SSL_H 
 #define HEADER_SSL_H 
 
 #include 
 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #ifndef OPENSSL_NO_BIO
 #include 
 #endif
 #ifndef OPENSSL_NO_DEPRECATED
 #ifndef OPENSSL_NO_X509
 #include 
 #endif
 #include 
 #include 
 #include 
 #endif
 #include 
 #include 
 
 #include 
 #include 
 #include 
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* SSLeay version number for ASN.1 encoding of the session information */
 /* Version 0 - initial version
  * Version 1 - added the optional peer certificate
  */
 #define SSL_SESSION_ASN1_VERSION 0x0001
 
 /* text strings for the ciphers */
 #define SSL_TXT_NULL_WITH_MD5		SSL2_TXT_NULL_WITH_MD5			
 #define SSL_TXT_RC4_128_WITH_MD5	SSL2_TXT_RC4_128_WITH_MD5		
 #define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	
 #define SSL_TXT_RC2_128_CBC_WITH_MD5	SSL2_TXT_RC2_128_CBC_WITH_MD5		
 #define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	
 #define SSL_TXT_IDEA_128_CBC_WITH_MD5	SSL2_TXT_IDEA_128_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_MD5	SSL2_TXT_DES_64_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_SHA	SSL2_TXT_DES_64_CBC_WITH_SHA		
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	
 
 /*    VRS Additional Kerberos5 entries
  */
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA
 #define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5       
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5       
 #define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5
 #define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
 #define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256
 
 #define SSL_MAX_SSL_SESSION_ID_LENGTH		32
 #define SSL_MAX_SID_CTX_LENGTH			32
 
 #define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES	(512/8)
 #define SSL_MAX_KEY_ARG_LENGTH			8
 #define SSL_MAX_MASTER_KEY_LENGTH		48
 
 
 /* These are used to specify which ciphers to use and not to use */
 
 #define SSL_TXT_EXP40		"EXPORT40"
 #define SSL_TXT_EXP56		"EXPORT56"
 #define SSL_TXT_LOW		"LOW"
 #define SSL_TXT_MEDIUM		"MEDIUM"
 #define SSL_TXT_HIGH		"HIGH"
 #define SSL_TXT_FIPS		"FIPS"
 
 #define SSL_TXT_kFZA		"kFZA" /* unused! */
 #define	SSL_TXT_aFZA		"aFZA" /* unused! */
 #define SSL_TXT_eFZA		"eFZA" /* unused! */
 #define SSL_TXT_FZA		"FZA"  /* unused! */
 
 #define	SSL_TXT_aNULL		"aNULL"
 #define	SSL_TXT_eNULL		"eNULL"
 #define	SSL_TXT_NULL		"NULL"
 
 #define SSL_TXT_kRSA		"kRSA"
 #define SSL_TXT_kDHr		"kDHr" /* no such ciphersuites supported! */
 #define SSL_TXT_kDHd		"kDHd" /* no such ciphersuites supported! */
 #define SSL_TXT_kDH 		"kDH"  /* no such ciphersuites supported! */
 #define SSL_TXT_kEDH		"kEDH"
 #define SSL_TXT_kKRB5     	"kKRB5"
 #define SSL_TXT_kECDHr		"kECDHr"
 #define SSL_TXT_kECDHe		"kECDHe"
 #define SSL_TXT_kECDH		"kECDH"
 #define SSL_TXT_kEECDH		"kEECDH"
 #define SSL_TXT_kPSK            "kPSK"
 #define SSL_TXT_kGOST		"kGOST"
 #define SSL_TXT_kSRP		"kSRP"
 
 #define	SSL_TXT_aRSA		"aRSA"
 #define	SSL_TXT_aDSS		"aDSS"
 #define	SSL_TXT_aDH		"aDH" /* no such ciphersuites supported! */
 #define	SSL_TXT_aECDH		"aECDH"
 #define SSL_TXT_aKRB5     	"aKRB5"
 #define SSL_TXT_aECDSA		"aECDSA"
 #define SSL_TXT_aPSK            "aPSK"
 #define SSL_TXT_aGOST94	"aGOST94"
 #define SSL_TXT_aGOST01 "aGOST01"
 #define SSL_TXT_aGOST  "aGOST"
 #define SSL_TXT_aSRP            "aSRP"
 
 #define	SSL_TXT_DSS		"DSS"
 #define SSL_TXT_DH		"DH"
 #define SSL_TXT_EDH		"EDH" /* same as "kEDH:-ADH" */
 #define SSL_TXT_ADH		"ADH"
 #define SSL_TXT_RSA		"RSA"
 #define SSL_TXT_ECDH		"ECDH"
 #define SSL_TXT_EECDH		"EECDH" /* same as "kEECDH:-AECDH" */
 #define SSL_TXT_AECDH		"AECDH"
 #define SSL_TXT_ECDSA		"ECDSA"
 #define SSL_TXT_KRB5      	"KRB5"
 #define SSL_TXT_PSK             "PSK"
 #define SSL_TXT_SRP		"SRP"
 
 #define SSL_TXT_DES		"DES"
 #define SSL_TXT_3DES		"3DES"
 #define SSL_TXT_RC4		"RC4"
 #define SSL_TXT_RC2		"RC2"
 #define SSL_TXT_IDEA		"IDEA"
 #define SSL_TXT_SEED		"SEED"
 #define SSL_TXT_AES128		"AES128"
 #define SSL_TXT_AES256		"AES256"
 #define SSL_TXT_AES		"AES"
 #define SSL_TXT_AES_GCM		"AESGCM"
 #define SSL_TXT_CAMELLIA128	"CAMELLIA128"
 #define SSL_TXT_CAMELLIA256	"CAMELLIA256"
 #define SSL_TXT_CAMELLIA	"CAMELLIA"
 
 #define SSL_TXT_MD5		"MD5"
 #define SSL_TXT_SHA1		"SHA1"
 #define SSL_TXT_SHA		"SHA" /* same as "SHA1" */
 #define SSL_TXT_GOST94		"GOST94" 
 #define SSL_TXT_GOST89MAC		"GOST89MAC" 
 #define SSL_TXT_SHA256		"SHA256"
 #define SSL_TXT_SHA384		"SHA384"
 
 #define SSL_TXT_SSLV2		"SSLv2"
 #define SSL_TXT_SSLV3		"SSLv3"
 #define SSL_TXT_TLSV1		"TLSv1"
 #define SSL_TXT_TLSV1_1		"TLSv1.1"
 #define SSL_TXT_TLSV1_2		"TLSv1.2"
 
 #define SSL_TXT_EXP		"EXP"
 #define SSL_TXT_EXPORT		"EXPORT"
 
 #define SSL_TXT_ALL		"ALL"
 
 /*
  * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
  * ciphers normally not being used.
  * Example: "RC4" will activate all ciphers using RC4 including ciphers
  * without authentication, which would normally disabled by DEFAULT (due
  * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
  * will make sure that it is also disabled in the specific selection.
  * COMPLEMENTOF* identifiers are portable between version, as adjustments
  * to the default cipher setup will also be included here.
  *
  * COMPLEMENTOFDEFAULT does not experience the same special treatment that
  * DEFAULT gets, as only selection is being done and no sorting as needed
  * for DEFAULT.
  */
 #define SSL_TXT_CMPALL		"COMPLEMENTOFALL"
 #define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT"
 
 /* The following cipher list is used by default.
  * It also is substituted when an application-defined cipher list string
  * starts with 'DEFAULT'. */
 #define SSL_DEFAULT_CIPHER_LIST	"ALL:!aNULL:!eNULL:!SSLv2"
 /* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
  * starts with a reasonable order, and all we have to do for DEFAULT is
  * throwing out anonymous and unencrypted ciphersuites!
  * (The latter are not actually enabled by ALL, but "ALL:RSA" would enable
  * some of them.)
  */
 
 /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
 #define SSL_SENT_SHUTDOWN	1
 #define SSL_RECEIVED_SHUTDOWN	2
 
 #ifdef __cplusplus
 }
 #endif
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 #if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
 #define OPENSSL_NO_SSL2
 #endif
 
 #define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
 #define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
 
 /* This is needed to stop compilers complaining about the
  * 'struct ssl_st *' function parameters used to prototype callbacks
  * in SSL_CTX. */
 typedef struct ssl_st *ssl_crock_st;
 typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
 typedef struct ssl_method_st SSL_METHOD;
 typedef struct ssl_cipher_st SSL_CIPHER;
 typedef struct ssl_session_st SSL_SESSION;
 
 DECLARE_STACK_OF(SSL_CIPHER)
 
 /* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
 typedef struct srtp_protection_profile_st
        {
        const char *name;
        unsigned long id;
        } SRTP_PROTECTION_PROFILE;
 
 DECLARE_STACK_OF(SRTP_PROTECTION_PROFILE)
 
 typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
 typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
 
 
 #ifndef OPENSSL_NO_SSL_INTERN
 
 /* used to hold info on the particular ciphers used */
 struct ssl_cipher_st
 	{
 	int valid;
 	const char *name;		/* text name */
 	unsigned long id;		/* id, 4 bytes, first is version */
 
 	/* changed in 0.9.9: these four used to be portions of a single value 'algorithms' */
 	unsigned long algorithm_mkey;	/* key exchange algorithm */
 	unsigned long algorithm_auth;	/* server authentication */
 	unsigned long algorithm_enc;	/* symmetric encryption */
 	unsigned long algorithm_mac;	/* symmetric authentication */
 	unsigned long algorithm_ssl;	/* (major) protocol version */
 
 	unsigned long algo_strength;	/* strength and export flags */
 	unsigned long algorithm2;	/* Extra flags */
 	int strength_bits;		/* Number of bits really used */
 	int alg_bits;			/* Number of bits for algorithm */
 	};
 
 
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 struct ssl_method_st
 	{
 	int version;
 	int (*ssl_new)(SSL *s);
 	void (*ssl_clear)(SSL *s);
 	void (*ssl_free)(SSL *s);
 	int (*ssl_accept)(SSL *s);
 	int (*ssl_connect)(SSL *s);
 	int (*ssl_read)(SSL *s,void *buf,int len);
 	int (*ssl_peek)(SSL *s,void *buf,int len);
 	int (*ssl_write)(SSL *s,const void *buf,int len);
 	int (*ssl_shutdown)(SSL *s);
 	int (*ssl_renegotiate)(SSL *s);
 	int (*ssl_renegotiate_check)(SSL *s);
 	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
 		max, int *ok);
 	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, 
 		int peek);
 	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
 	int (*ssl_dispatch_alert)(SSL *s);
 	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
 	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
 	const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
 	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
 	int (*ssl_pending)(const SSL *s);
 	int (*num_ciphers)(void);
 	const SSL_CIPHER *(*get_cipher)(unsigned ncipher);
 	const struct ssl_method_st *(*get_ssl_method)(int version);
 	long (*get_timeout)(void);
 	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
 	int (*ssl_version)(void);
 	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
 	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
 	};
 
 /* Lets make this into an ASN.1 type structure as follows
  * SSL_SESSION_ID ::= SEQUENCE {
  *	version 		INTEGER,	-- structure version number
  *	SSLversion 		INTEGER,	-- SSL version number
  *	Cipher 			OCTET STRING,	-- the 3 byte cipher ID
  *	Session_ID 		OCTET STRING,	-- the Session ID
  *	Master_key 		OCTET STRING,	-- the master key
  *	KRB5_principal		OCTET STRING	-- optional Kerberos principal
  *	Key_Arg [ 0 ] IMPLICIT	OCTET STRING,	-- the optional Key argument
  *	Time [ 1 ] EXPLICIT	INTEGER,	-- optional Start Time
  *	Timeout [ 2 ] EXPLICIT	INTEGER,	-- optional Timeout ins seconds
  *	Peer [ 3 ] EXPLICIT	X509,		-- optional Peer Certificate
  *	Session_ID_context [ 4 ] EXPLICIT OCTET STRING,   -- the Session ID context
  *	Verify_result [ 5 ] EXPLICIT INTEGER,   -- X509_V_... code for `Peer'
  *	HostName [ 6 ] EXPLICIT OCTET STRING,   -- optional HostName from servername TLS extension 
  *	PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint
  *	PSK_identity [ 8 ] EXPLICIT OCTET STRING,  -- optional PSK identity
  *	Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket
  *	Ticket [10]             EXPLICIT OCTET STRING, -- session ticket (clients only)
  *	Compression_meth [11]   EXPLICIT OCTET STRING, -- optional compression method
  *	SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username
  *	}
  * Look in ssl/ssl_asn1.c for more details
  * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
  */
 struct ssl_session_st
 	{
 	int ssl_version;	/* what ssl version session info is
 				 * being kept in here? */
 
 	/* only really used in SSLv2 */
 	unsigned int key_arg_length;
 	unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
 	int master_key_length;
 	unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
 	/* session_id - valid? */
 	unsigned int session_id_length;
 	unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
 	/* this is used to determine whether the session is being reused in
 	 * the appropriate context. It is up to the application to set this,
 	 * via SSL_new */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 #ifndef OPENSSL_NO_KRB5
         unsigned int krb5_client_princ_len;
         unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
 #endif /* OPENSSL_NO_KRB5 */
 #ifndef OPENSSL_NO_PSK
 	char *psk_identity_hint;
 	char *psk_identity;
 #endif
 	/* Used to indicate that session resumption is not allowed.
 	 * Applications can also set this bit for a new session via
 	 * not_resumable_session_cb to disable session caching and tickets. */
 	int not_resumable;
 
 	/* The cert is the certificate used to establish this connection */
 	struct sess_cert_st /* SESS_CERT */ *sess_cert;
 
 	/* This is the cert for the other end.
 	 * On clients, it will be the same as sess_cert->peer_key->x509
 	 * (the latter is not enough as sess_cert is not retained
 	 * in the external representation of sessions, see ssl_asn1.c). */
 	X509 *peer;
 	/* when app_verify_callback accepts a session where the peer's certificate
 	 * is not ok, we must remember the error for session reuse: */
 	long verify_result; /* only for servers */
 
 	int references;
 	long timeout;
 	long time;
 
 	unsigned int compress_meth;	/* Need to lookup the method */
 
 	const SSL_CIPHER *cipher;
 	unsigned long cipher_id;	/* when ASN.1 loaded, this
 					 * needs to be used to load
 					 * the 'cipher' structure */
 
 	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
 
 	CRYPTO_EX_DATA ex_data; /* application specific data */
 
 	/* These are used to make removal of session-ids more
 	 * efficient and to implement a maximum cache size. */
 	struct ssl_session_st *prev,*next;
 #ifndef OPENSSL_NO_TLSEXT
 	char *tlsext_hostname;
 #ifndef OPENSSL_NO_EC
 	size_t tlsext_ecpointformatlist_length;
 	unsigned char *tlsext_ecpointformatlist; /* peer's list */
 	size_t tlsext_ellipticcurvelist_length;
 	unsigned char *tlsext_ellipticcurvelist; /* peer's list */
 #endif /* OPENSSL_NO_EC */
 	/* RFC4507 info */
 	unsigned char *tlsext_tick;	/* Session ticket */
 	size_t tlsext_ticklen;		/* Session ticket length */
 	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */
 #endif
 #ifndef OPENSSL_NO_SRP
 	char *srp_username;
 #endif
 	};
 
 #endif
 
 #define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
 #define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
 /* Allow initial connection to servers that don't support RI */
 #define SSL_OP_LEGACY_SERVER_CONNECT			0x00000004L
 #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG		0x00000008L
 #define SSL_OP_TLSEXT_PADDING				0x00000010L
 #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER		0x00000020L
 #define SSL_OP_SAFARI_ECDHE_ECDSA_BUG			0x00000040L
 #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
 #define SSL_OP_TLS_D5_BUG				0x00000100L
 #define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
 
 /* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */
 #define SSL_OP_MSIE_SSLV2_RSA_PADDING			0x0
 /* Refers to ancient SSLREF and SSLv2, retained for compatibility */
 #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG		0x0
 
 /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
  * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
  * the workaround is not needed.  Unfortunately some broken SSL/TLS
  * implementations cannot handle it at all, which is why we include
  * it in SSL_OP_ALL. */
 #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */
 
 /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
  *             This used to be 0x000FFFFFL before 0.9.7. */
 #define SSL_OP_ALL					0x80000BFFL
 
 /* DTLS options */
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
 /* Turn on Cookie Exchange (on relevant for servers) */
 #define SSL_OP_COOKIE_EXCHANGE              0x00002000L
 /* Don't use RFC4507 ticket extension */
 #define SSL_OP_NO_TICKET	            0x00004000L
 /* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */
 #define SSL_OP_CISCO_ANYCONNECT		    0x00008000L
 
 /* As server, disallow session resumption on renegotiation */
 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L
 /* Don't use compression even if supported */
 #define SSL_OP_NO_COMPRESSION				0x00020000L
 /* Permit unsafe legacy renegotiation */
 #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L
 /* If set, always create a new key when using tmp_ecdh parameters */
 #define SSL_OP_SINGLE_ECDH_USE				0x00080000L
 /* If set, always create a new key when using tmp_dh parameters */
 #define SSL_OP_SINGLE_DH_USE				0x00100000L
 /* Does nothing: retained for compatibiity */
 #define SSL_OP_EPHEMERAL_RSA				0x0
 /* Set on servers to choose the cipher according to the server's
  * preferences */
 #define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L
 /* If set, a server will allow a client to issue a SSLv3.0 version number
  * as latest version supported in the premaster secret, even when TLSv1.0
  * (version 3.1) was announced in the client hello. Normally this is
  * forbidden to prevent version rollback attacks. */
 #define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L
 
 #define SSL_OP_NO_SSLv2					0x01000000L
 #define SSL_OP_NO_SSLv3					0x02000000L
 #define SSL_OP_NO_TLSv1					0x04000000L
 #define SSL_OP_NO_TLSv1_2				0x08000000L
 #define SSL_OP_NO_TLSv1_1				0x10000000L
 
 /* These next two were never actually used for anything since SSLeay
  * zap so we have some more flags.
  */
 /* The next flag deliberately changes the ciphertest, this is a check
  * for the PKCS#1 attack */
 #define SSL_OP_PKCS1_CHECK_1				0x0
 #define SSL_OP_PKCS1_CHECK_2				0x0
 
 #define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L
 /* Make server add server-hello extension from early version of
  * cryptopro draft, when GOST ciphersuite is negotiated. 
  * Required for interoperability with CryptoPro CSP 3.x 
  */
 #define SSL_OP_CRYPTOPRO_TLSEXT_BUG			0x80000000L
 
 /* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
  * when just a single record has been written): */
 #define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
 /* Make it possible to retry SSL_write() with changed buffer location
  * (buffer contents must stay the same!); this is not the default to avoid
  * the misconception that non-blocking SSL_write() behaves like
  * non-blocking write(): */
 #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
 /* Never bother the application with retries if the transport
  * is blocking: */
 #define SSL_MODE_AUTO_RETRY 0x00000004L
 /* Don't attempt to automatically build certificate chain */
 #define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
 /* Save RAM by releasing read and write buffers when they're empty. (SSL3 and
  * TLS only.)  "Released" buffers are put onto a free-list in the context
  * or just freed (depending on the context's setting for freelist_max_len). */
 #define SSL_MODE_RELEASE_BUFFERS 0x00000010L
 /* Send the current time in the Random fields of the ClientHello and
  * ServerHello records for compatibility with hypothetical implementations
  * that require it.
  */
 #define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020L
 #define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040L
 /* Send TLS_FALLBACK_SCSV in the ClientHello.
  * To be set only by applications that reconnect with a downgraded protocol
  * version; see draft-ietf-tls-downgrade-scsv-00 for details.
  *
  * DO NOT ENABLE THIS if your application attempts a normal handshake.
  * Only use this in explicit fallback retries, following the guidance
  * in draft-ietf-tls-downgrade-scsv-00.
  */
 #define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L
 
 /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
  * they cannot be used to clear bits. */
 
 #define SSL_CTX_set_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_CTX_clear_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_CTX_get_options(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
 #define SSL_set_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_clear_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_get_options(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
 
 #define SSL_CTX_set_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
 #define SSL_CTX_clear_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_CTX_get_mode(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
 #define SSL_clear_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_set_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
 #define SSL_get_mode(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
 #define SSL_set_mtu(ssl, mtu) \
         SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
 #define DTLS_set_link_mtu(ssl, mtu) \
         SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
 #define DTLS_get_link_min_mtu(ssl) \
         SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)
 
 #define SSL_get_secure_renegotiation_support(ssl) \
 	SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
 
 #ifndef OPENSSL_NO_HEARTBEATS
 #define SSL_heartbeat(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_TLS_EXT_SEND_HEARTBEAT,0,NULL)
 #endif
 
 void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 #define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 #define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 
 #ifndef OPENSSL_NO_SRP
 
 #ifndef OPENSSL_NO_SSL_INTERN
 
 typedef struct srp_ctx_st
 	{
 	/* param for all the callbacks */
 	void *SRP_cb_arg;
 	/* set client Hello login callback */
 	int (*TLS_ext_srp_username_callback)(SSL *, int *, void *);
 	/* set SRP N/g param callback for verification */
 	int (*SRP_verify_param_callback)(SSL *, void *);
 	/* set SRP client passwd callback */
 	char *(*SRP_give_srp_client_pwd_callback)(SSL *, void *);
 
 	char *login;
 	BIGNUM *N,*g,*s,*B,*A;
 	BIGNUM *a,*b,*v;
 	char *info;
 	int strength;
 
 	unsigned long srp_Mask;
 	} SRP_CTX;
 
 #endif
 
 /* see tls_srp.c */
 int SSL_SRP_CTX_init(SSL *s);
 int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
 int SSL_SRP_CTX_free(SSL *ctx);
 int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
 int SSL_srp_server_param_with_username(SSL *s, int *ad);
 int SRP_generate_server_master_secret(SSL *s,unsigned char *master_key);
 int SRP_Calc_A_param(SSL *s);
 int SRP_generate_client_master_secret(SSL *s,unsigned char *master_key);
 
 #endif
 
 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
 #else
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
 #endif
 
 #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
 
 /* This callback type is used inside SSL_CTX, SSL, and in the functions that set
  * them. It is used to override the generation of SSL/TLS session IDs in a
  * server. Return value should be zero on an error, non-zero to proceed. Also,
  * callbacks should themselves check if the id they generate is unique otherwise
  * the SSL handshake will fail with an error - callbacks can do this using the
  * 'ssl' value they're passed by;
  *      SSL_has_matching_session_id(ssl, id, *id_len)
  * The length value passed in is set at the maximum size the session ID can be.
  * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
  * can alter this length to be less if desired, but under SSLv2 session IDs are
  * supposed to be fixed at 16 bytes so the id will be padded after the callback
  * returns in this case. It is also an error for the callback to set the size to
  * zero. */
 typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len);
 
 typedef struct ssl_comp_st SSL_COMP;
 
 #ifndef OPENSSL_NO_SSL_INTERN
 
 struct ssl_comp_st
 	{
 	int id;
 	const char *name;
 #ifndef OPENSSL_NO_COMP
 	COMP_METHOD *method;
 #else
 	char *method;
 #endif
 	};
 
 DECLARE_STACK_OF(SSL_COMP)
 DECLARE_LHASH_OF(SSL_SESSION);
 
 struct ssl_ctx_st
 	{
 	const SSL_METHOD *method;
 
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	/* same as above but sorted for lookup */
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	struct x509_store_st /* X509_STORE */ *cert_store;
 	LHASH_OF(SSL_SESSION) *sessions;
 	/* Most session-ids that will be cached, default is
 	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
 	unsigned long session_cache_size;
 	struct ssl_session_st *session_cache_head;
 	struct ssl_session_st *session_cache_tail;
 
 	/* This can have one of 2 values, ored together,
 	 * SSL_SESS_CACHE_CLIENT,
 	 * SSL_SESS_CACHE_SERVER,
 	 * Default is SSL_SESSION_CACHE_SERVER, which means only
 	 * SSL_accept which cache SSL_SESSIONS. */
 	int session_cache_mode;
 
 	/* If timeout is not 0, it is the default timeout value set
 	 * when SSL_new() is called.  This has been put in to make
 	 * life easier to set things up */
 	long session_timeout;
 
 	/* If this callback is not null, it will be called each
 	 * time a session id is added to the cache.  If this function
 	 * returns 1, it means that the callback will do a
 	 * SSL_SESSION_free() when it has finished using it.  Otherwise,
 	 * on 0, it means the callback has finished with it.
 	 * If remove_session_cb is not null, it will be called when
 	 * a session-id is removed from the cache.  After the call,
 	 * OpenSSL will SSL_SESSION_free() it. */
 	int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
 	void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
 	SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
 		unsigned char *data,int len,int *copy);
 
 	struct
 		{
 		int sess_connect;	/* SSL new conn - started */
 		int sess_connect_renegotiate;/* SSL reneg - requested */
 		int sess_connect_good;	/* SSL new conne/reneg - finished */
 		int sess_accept;	/* SSL new accept - started */
 		int sess_accept_renegotiate;/* SSL reneg - requested */
 		int sess_accept_good;	/* SSL accept/reneg - finished */
 		int sess_miss;		/* session lookup misses  */
 		int sess_timeout;	/* reuse attempt on timeouted session */
 		int sess_cache_full;	/* session removed due to full cache */
 		int sess_hit;		/* session reuse actually done */
 		int sess_cb_hit;	/* session-id that was not
 					 * in the cache was
 					 * passed back via the callback.  This
 					 * indicates that the application is
 					 * supplying session-id's from other
 					 * processes - spooky :-) */
 		} stats;
 
 	int references;
 
 	/* if defined, these override the X509_verify_cert() calls */
 	int (*app_verify_callback)(X509_STORE_CTX *, void *);
 	void *app_verify_arg;
 	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
 	 * ('app_verify_callback' was called with just one argument) */
 
 	/* Default password callback. */
 	pem_password_cb *default_passwd_callback;
 
 	/* Default password callback user data. */
 	void *default_passwd_callback_userdata;
 
 	/* get client cert callback */
 	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 
     /* cookie generate callback */
     int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int *cookie_len);
 
     /* verify cookie callback */
     int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int cookie_len);
 
 	CRYPTO_EX_DATA ex_data;
 
 	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
 	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
 	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
 
 	STACK_OF(X509) *extra_certs;
 	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
 
 
 	/* Default values used when no per-SSL value is defined follow */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
 
 	/* what we put in client cert requests */
 	STACK_OF(X509_NAME) *client_CA;
 
 
 	/* Default values to use in SSL structures follow (these are copied by SSL_new) */
 
 	unsigned long options;
 	unsigned long mode;
 	long max_cert_list;
 
 	struct cert_st /* CERT */ *cert;
 	int read_ahead;
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int verify_mode;
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	int quiet_shutdown;
 
 	/* Maximum amount of data to send in one fragment.
 	 * actual record size can be more than this due to
 	 * padding and MAC overheads.
 	 */
 	unsigned int max_send_fragment;
 
 #ifndef OPENSSL_NO_ENGINE
 	/* Engine to pass requests for client certs to
 	 */
 	ENGINE *client_cert_engine;
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions servername callback */
 	int (*tlsext_servername_callback)(SSL*, int *, void *);
 	void *tlsext_servername_arg;
 	/* RFC 4507 session ticket keys */
 	unsigned char tlsext_tick_key_name[16];
 	unsigned char tlsext_tick_hmac_key[16];
 	unsigned char tlsext_tick_aes_key[16];
 	/* Callback to support customisation of ticket key setting */
 	int (*tlsext_ticket_key_cb)(SSL *ssl,
 					unsigned char *name, unsigned char *iv,
 					EVP_CIPHER_CTX *ectx,
  					HMAC_CTX *hctx, int enc);
 
 	/* certificate status request info */
 	/* Callback for status request */
 	int (*tlsext_status_cb)(SSL *ssl, void *arg);
 	void *tlsext_status_arg;
 
 	/* draft-rescorla-tls-opaque-prf-input-00.txt information */
 	int (*tlsext_opaque_prf_input_callback)(SSL *, void *peerinput, size_t len, void *arg);
 	void *tlsext_opaque_prf_input_callback_arg;
 #endif
 
 #ifndef OPENSSL_NO_PSK
 	char *psk_identity_hint;
 	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
 		unsigned int max_identity_len, unsigned char *psk,
 		unsigned int max_psk_len);
 	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
 		unsigned char *psk, unsigned int max_psk_len);
 #endif
 
 #ifndef OPENSSL_NO_BUF_FREELISTS
 #define SSL_MAX_BUF_FREELIST_LEN_DEFAULT 32
 	unsigned int freelist_max_len;
 	struct ssl3_buf_freelist_st *wbuf_freelist;
 	struct ssl3_buf_freelist_st *rbuf_freelist;
 #endif
 #ifndef OPENSSL_NO_SRP
 	SRP_CTX srp_ctx; /* ctx for SRP authentication */
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
 
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	/* Next protocol negotiation information */
 	/* (for experimental NPN extension). */
 
 	/* For a server, this contains a callback function by which the set of
 	 * advertised protocols can be provided. */
 	int (*next_protos_advertised_cb)(SSL *s, const unsigned char **buf,
 			                 unsigned int *len, void *arg);
 	void *next_protos_advertised_cb_arg;
 	/* For a client, this contains a callback function that selects the
 	 * next protocol from the list provided by the server. */
 	int (*next_proto_select_cb)(SSL *s, unsigned char **out,
 				    unsigned char *outlen,
 				    const unsigned char *in,
 				    unsigned int inlen,
 				    void *arg);
 	void *next_proto_select_cb_arg;
 # endif
         /* SRTP profiles we are willing to do from RFC 5764 */
         STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  
 #endif
 	};
 
 #endif
 
 #define SSL_SESS_CACHE_OFF			0x0000
 #define SSL_SESS_CACHE_CLIENT			0x0001
 #define SSL_SESS_CACHE_SERVER			0x0002
 #define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
 #define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
 /* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
 #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
 #define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200
 #define SSL_SESS_CACHE_NO_INTERNAL \
 	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
 
 LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
 #define SSL_CTX_sess_number(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
 #define SSL_CTX_sess_connect(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
 #define SSL_CTX_sess_connect_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
 #define SSL_CTX_sess_connect_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
 #define SSL_CTX_sess_accept_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
 #define SSL_CTX_sess_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
 #define SSL_CTX_sess_cb_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
 #define SSL_CTX_sess_misses(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
 #define SSL_CTX_sess_timeouts(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
 #define SSL_CTX_sess_cache_full(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
 SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
 #endif
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
 #ifndef OPENSSL_NO_NEXTPROTONEG
 void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
 					   int (*cb) (SSL *ssl,
 						      const unsigned char **out,
 						      unsigned int *outlen,
 						      void *arg),
 					   void *arg);
 void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
 				      int (*cb) (SSL *ssl,
 						 unsigned char **out,
 						 unsigned char *outlen,
 						 const unsigned char *in,
 						 unsigned int inlen,
 						 void *arg),
 				      void *arg);
 
 int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
 			  const unsigned char *in, unsigned int inlen,
 			  const unsigned char *client, unsigned int client_len);
 void SSL_get0_next_proto_negotiated(const SSL *s,
 				    const unsigned char **data, unsigned *len);
 
 #define OPENSSL_NPN_UNSUPPORTED	0
 #define OPENSSL_NPN_NEGOTIATED	1
 #define OPENSSL_NPN_NO_OVERLAP	2
 #endif
 
 #ifndef OPENSSL_NO_PSK
 /* the maximum length of the buffer given to callbacks containing the
  * resulting identity/psk */
 #define PSK_MAX_IDENTITY_LEN 128
 #define PSK_MAX_PSK_LEN 256
 void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, 
 	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, 
 		char *identity, unsigned int max_identity_len, unsigned char *psk,
 		unsigned int max_psk_len));
 void SSL_set_psk_client_callback(SSL *ssl, 
 	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, 
 		char *identity, unsigned int max_identity_len, unsigned char *psk,
 		unsigned int max_psk_len));
 void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, 
 	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
 		unsigned char *psk, unsigned int max_psk_len));
 void SSL_set_psk_server_callback(SSL *ssl,
 	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
 		unsigned char *psk, unsigned int max_psk_len));
 int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
 int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
 const char *SSL_get_psk_identity_hint(const SSL *s);
 const char *SSL_get_psk_identity(const SSL *s);
 #endif
 
 #define SSL_NOTHING	1
 #define SSL_WRITING	2
 #define SSL_READING	3
 #define SSL_X509_LOOKUP	4
 
 /* These will only be used when doing non-blocking IO */
 #define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
 #define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
 #define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
 #define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
 
 #define SSL_MAC_FLAG_READ_MAC_STREAM 1
 #define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
 
 #ifndef OPENSSL_NO_SSL_INTERN
 
 struct ssl_st
 	{
 	/* protocol version
 	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
 	 */
 	int version;
 	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
 
 	const SSL_METHOD *method; /* SSLv3 */
 
 	/* There are 2 BIO's even though they are normally both the
 	 * same.  This is so data can be read and written to different
 	 * handlers */
 
 #ifndef OPENSSL_NO_BIO
 	BIO *rbio; /* used by SSL_read */
 	BIO *wbio; /* used by SSL_write */
 	BIO *bbio; /* used during session-id reuse to concatenate
 		    * messages */
 #else
 	char *rbio; /* used by SSL_read */
 	char *wbio; /* used by SSL_write */
 	char *bbio;
 #endif
 	/* This holds a variable that indicates what we were doing
 	 * when a 0 or -1 is returned.  This is needed for
 	 * non-blocking IO so we know what request needs re-doing when
 	 * in SSL_accept or SSL_connect */
 	int rwstate;
 
 	/* true when we are actually in SSL_accept() or SSL_connect() */
 	int in_handshake;
 	int (*handshake_func)(SSL *);
 
 	/* Imagine that here's a boolean member "init" that is
 	 * switched as soon as SSL_set_{accept/connect}_state
 	 * is called for the first time, so that "state" and
 	 * "handshake_func" are properly initialized.  But as
 	 * handshake_func is == 0 until then, we use this
 	 * test instead of an "init" member.
 	 */
 
 	int server;	/* are we the server side? - mostly used by SSL_clear*/
 
 	int new_session;/* Generate a new session or reuse an old one.
 	                 * NB: For servers, the 'new' session may actually be a previously
 	                 * cached session or even the previous session unless
 	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 	int quiet_shutdown;/* don't send shutdown packets */
 	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
 			 * for received */
 	int state;	/* where we are */
 	int rstate;	/* where we are when reading */
 
 	BUF_MEM *init_buf;	/* buffer used during init */
 	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */
 	int init_num;		/* amount read/written */
 	int init_off;		/* amount read/written */
 
 	/* used internally to point at a raw packet */
 	unsigned char *packet;
 	unsigned int packet_length;
 
 	struct ssl2_state_st *s2; /* SSLv2 variables */
 	struct ssl3_state_st *s3; /* SSLv3 variables */
 	struct dtls1_state_st *d1; /* DTLSv1 variables */
 
 	int read_ahead;		/* Read as many input bytes as possible
 	               	 	 * (for non-blocking reads) */
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int hit;		/* reusing a previous session */
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	/* crypto */
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	/* These are the ones being used, the ones in SSL_SESSION are
 	 * the ones to be 'copied' into these ones */
 	int mac_flags; 
 	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
 	EVP_MD_CTX *read_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *expand;			/* uncompress */
 #else
 	char *expand;
 #endif
 
 	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
 	EVP_MD_CTX *write_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *compress;			/* compression */
 #else
 	char *compress;	
 #endif
 
 	/* session info */
 
 	/* client cert? */
 	/* This is used to hold the server certificate used */
 	struct cert_st /* CERT */ *cert;
 
 	/* the session_id_context is used to ensure sessions are only reused
 	 * in the appropriate context */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 	/* This can also be in the session once a session is established */
 	SSL_SESSION *session;
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	/* Used in SSL2 and SSL3 */
 	int verify_mode;	/* 0 don't care about verify failure.
 				 * 1 fail if verify fails */
 	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
 
 	int error;		/* error bytes to be written */
 	int error_code;		/* actual code */
 
 #ifndef OPENSSL_NO_KRB5
 	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
 #endif	/* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_PSK
 	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
 		unsigned int max_identity_len, unsigned char *psk,
 		unsigned int max_psk_len);
 	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
 		unsigned char *psk, unsigned int max_psk_len);
 #endif
 
 	SSL_CTX *ctx;
 	/* set this flag to 1 and a sleep(1) is put into all SSL_read()
 	 * and SSL_write() calls, good for nbio debuging :-) */
 	int debug;	
 
 	/* extra application data */
 	long verify_result;
 	CRYPTO_EX_DATA ex_data;
 
 	/* for server side, keep the list of CA_dn we can use */
 	STACK_OF(X509_NAME) *client_CA;
 
 	int references;
 	unsigned long options; /* protocol behaviour */
 	unsigned long mode; /* API behaviour */
 	long max_cert_list;
 	int first_packet;
 	int client_version;	/* what was passed, used for
 				 * SSLv3/TLS rollback check */
 	unsigned int max_send_fragment;
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extension debug callback */
 	void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
 					unsigned char *data, int len,
 					void *arg);
 	void *tlsext_debug_arg;
 	char *tlsext_hostname;
 	int servername_done;   /* no further mod of servername 
 	                          0 : call the servername extension callback.
 	                          1 : prepare 2, allow last ack just after in server callback.
 	                          2 : don't call servername callback, no ack in server hello
 	                       */
 	/* certificate status request info */
 	/* Status type or -1 if no status type */
 	int tlsext_status_type;
 	/* Expect OCSP CertificateStatus message */
 	int tlsext_status_expected;
 	/* OCSP status request only */
 	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
 	X509_EXTENSIONS *tlsext_ocsp_exts;
 	/* OCSP response received or to be sent */
 	unsigned char *tlsext_ocsp_resp;
 	int tlsext_ocsp_resplen;
 
 	/* RFC4507 session ticket expected to be received or sent */
 	int tlsext_ticket_expected;
 #ifndef OPENSSL_NO_EC
 	size_t tlsext_ecpointformatlist_length;
 	unsigned char *tlsext_ecpointformatlist; /* our list */
 	size_t tlsext_ellipticcurvelist_length;
 	unsigned char *tlsext_ellipticcurvelist; /* our list */
 #endif /* OPENSSL_NO_EC */
 
 	/* draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */
 	void *tlsext_opaque_prf_input;
 	size_t tlsext_opaque_prf_input_len;
 
 	/* TLS Session Ticket extension override */
 	TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
 
 	/* TLS Session Ticket extension callback */
 	tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
 	void *tls_session_ticket_ext_cb_arg;
 
 	/* TLS pre-shared secret session resumption */
 	tls_session_secret_cb_fn tls_session_secret_cb;
 	void *tls_session_secret_cb_arg;
 
 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	/* Next protocol negotiation. For the client, this is the protocol that
 	 * we sent in NextProtocol and is set when handling ServerHello
 	 * extensions.
 	 *
 	 * For a server, this is the client's selected_protocol from
 	 * NextProtocol and is set when handling the NextProtocol message,
 	 * before the Finished message. */
 	unsigned char *next_proto_negotiated;
 	unsigned char next_proto_negotiated_len;
 #endif
 
 #define session_ctx initial_ctx
 
 	STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  /* What we'll do */
 	SRTP_PROTECTION_PROFILE *srtp_profile;            /* What's been chosen */
 
 	unsigned int tlsext_heartbeat;  /* Is use of the Heartbeat extension negotiated?
 	                                   0: disabled
 	                                   1: enabled
 	                                   2: enabled, but not allowed to send Requests
 	                                 */
 	unsigned int tlsext_hb_pending; /* Indicates if a HeartbeatRequest is in flight */
 	unsigned int tlsext_hb_seq;     /* HeartbeatRequest sequence number */
 #else
 #define session_ctx ctx
 #endif /* OPENSSL_NO_TLSEXT */
 
 	int renegotiate;/* 1 if we are renegotiating.
 	                 * 2 if we are a server and are inside a handshake
 	                 * (i.e. not just sending a HelloRequest) */
 
 #ifndef OPENSSL_NO_SRP
 	SRP_CTX srp_ctx; /* ctx for SRP authentication */
 #endif
 	};
 
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #include 
 #include 
 #include  /* This is mostly sslv3 with a few tweaks */
 #include  /* Datagram TLS */
 #include 
 #include   /* Support for the use_srtp extension */
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* compatibility */
 #define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
 #define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
 #define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
 #define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
 #define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
 #define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
 
 /* The following are the possible values for ssl->state are are
  * used to indicate where we are up to in the SSL connection establishment.
  * The macros that follow are about the only things you should need to use
  * and even then, only when using non-blocking IO.
  * It can also be useful to work out where you were when the connection
  * failed */
 
 #define SSL_ST_CONNECT			0x1000
 #define SSL_ST_ACCEPT			0x2000
 #define SSL_ST_MASK			0x0FFF
 #define SSL_ST_INIT			(SSL_ST_CONNECT|SSL_ST_ACCEPT)
 #define SSL_ST_BEFORE			0x4000
 #define SSL_ST_OK			0x03
 #define SSL_ST_RENEGOTIATE		(0x04|SSL_ST_INIT)
 
 #define SSL_CB_LOOP			0x01
 #define SSL_CB_EXIT			0x02
 #define SSL_CB_READ			0x04
 #define SSL_CB_WRITE			0x08
 #define SSL_CB_ALERT			0x4000 /* used in callback */
 #define SSL_CB_READ_ALERT		(SSL_CB_ALERT|SSL_CB_READ)
 #define SSL_CB_WRITE_ALERT		(SSL_CB_ALERT|SSL_CB_WRITE)
 #define SSL_CB_ACCEPT_LOOP		(SSL_ST_ACCEPT|SSL_CB_LOOP)
 #define SSL_CB_ACCEPT_EXIT		(SSL_ST_ACCEPT|SSL_CB_EXIT)
 #define SSL_CB_CONNECT_LOOP		(SSL_ST_CONNECT|SSL_CB_LOOP)
 #define SSL_CB_CONNECT_EXIT		(SSL_ST_CONNECT|SSL_CB_EXIT)
 #define SSL_CB_HANDSHAKE_START		0x10
 #define SSL_CB_HANDSHAKE_DONE		0x20
 
 /* Is the SSL_connection established? */
 #define SSL_get_state(a)		SSL_state(a)
 #define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
 #define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
 #define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
 #define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
 #define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
  * you should not need these */
 #define SSL_ST_READ_HEADER			0xF0
 #define SSL_ST_READ_BODY			0xF1
 #define SSL_ST_READ_DONE			0xF2
 
 /* Obtain latest Finished message
  *   -- that we sent (SSL_get_finished)
  *   -- that we expected from peer (SSL_get_peer_finished).
  * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
 size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
 size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 
 /* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
  * are 'ored' with SSL_VERIFY_PEER if they are desired */
 #define SSL_VERIFY_NONE			0x00
 #define SSL_VERIFY_PEER			0x01
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
 #define SSL_VERIFY_CLIENT_ONCE		0x04
 
 #define OpenSSL_add_ssl_algorithms()	SSL_library_init()
 #define SSLeay_add_ssl_algorithms()	SSL_library_init()
 
 /* this is for backward compatibility */
 #if 0 /* NEW_SSLEAY */
 #define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
 #define SSL_set_pref_cipher(c,n)	SSL_set_cipher_list(c,n)
 #define SSL_add_session(a,b)            SSL_CTX_add_session((a),(b))
 #define SSL_remove_session(a,b)		SSL_CTX_remove_session((a),(b))
 #define SSL_flush_sessions(a,b)		SSL_CTX_flush_sessions((a),(b))
 #endif
 /* More backward compatibility */
 #define SSL_get_cipher(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_cipher_bits(s,np) \
 		SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
 #define SSL_get_cipher_version(s) \
 		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
 #define SSL_get_cipher_name(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_time(a)		SSL_SESSION_get_time(a)
 #define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
 #define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
 #define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
 
 #define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
 #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
 
 DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 
 #define SSL_AD_REASON_OFFSET		1000 /* offset to get SSL_R_... value from SSL_AD_... */
 
 /* These alert types are for SSLv3 and TLSv1 */
 #define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
 #define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
 #define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
 #define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
 #define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
 #define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
 #define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
 #define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
 #define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
 #define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
 #define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
 #define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
 #define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
 #define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
 #define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
 #define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
 #define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
 #define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
 #define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */
 #define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
 #define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
 #define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
 #define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
 #define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION
 #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 #define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME
 #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
 #define SSL_AD_INAPPROPRIATE_FALLBACK	TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */
 
 #define SSL_ERROR_NONE			0
 #define SSL_ERROR_SSL			1
 #define SSL_ERROR_WANT_READ		2
 #define SSL_ERROR_WANT_WRITE		3
 #define SSL_ERROR_WANT_X509_LOOKUP	4
 #define SSL_ERROR_SYSCALL		5 /* look at error stack/return value/errno */
 #define SSL_ERROR_ZERO_RETURN		6
 #define SSL_ERROR_WANT_CONNECT		7
 #define SSL_ERROR_WANT_ACCEPT		8
 
 #define SSL_CTRL_NEED_TMP_RSA			1
 #define SSL_CTRL_SET_TMP_RSA			2
 #define SSL_CTRL_SET_TMP_DH			3
 #define SSL_CTRL_SET_TMP_ECDH			4
 #define SSL_CTRL_SET_TMP_RSA_CB			5
 #define SSL_CTRL_SET_TMP_DH_CB			6
 #define SSL_CTRL_SET_TMP_ECDH_CB		7
 
 #define SSL_CTRL_GET_SESSION_REUSED		8
 #define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9
 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10
 #define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11
 #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12
 #define SSL_CTRL_GET_FLAGS			13
 #define SSL_CTRL_EXTRA_CHAIN_CERT		14
 
 #define SSL_CTRL_SET_MSG_CALLBACK               15
 #define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
 
 /* only applies to datagram connections */
 #define SSL_CTRL_SET_MTU                17
 /* Stats */
 #define SSL_CTRL_SESS_NUMBER			20
 #define SSL_CTRL_SESS_CONNECT			21
 #define SSL_CTRL_SESS_CONNECT_GOOD		22
 #define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23
 #define SSL_CTRL_SESS_ACCEPT			24
 #define SSL_CTRL_SESS_ACCEPT_GOOD		25
 #define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26
 #define SSL_CTRL_SESS_HIT			27
 #define SSL_CTRL_SESS_CB_HIT			28
 #define SSL_CTRL_SESS_MISSES			29
 #define SSL_CTRL_SESS_TIMEOUTS			30
 #define SSL_CTRL_SESS_CACHE_FULL		31
 #define SSL_CTRL_OPTIONS			32
 #define SSL_CTRL_MODE				33
 
 #define SSL_CTRL_GET_READ_AHEAD			40
 #define SSL_CTRL_SET_READ_AHEAD			41
 #define SSL_CTRL_SET_SESS_CACHE_SIZE		42
 #define SSL_CTRL_GET_SESS_CACHE_SIZE		43
 #define SSL_CTRL_SET_SESS_CACHE_MODE		44
 #define SSL_CTRL_GET_SESS_CACHE_MODE		45
 
 #define SSL_CTRL_GET_MAX_CERT_LIST		50
 #define SSL_CTRL_SET_MAX_CERT_LIST		51
 
 #define SSL_CTRL_SET_MAX_SEND_FRAGMENT		52
 
 /* see tls1.h for macros based on these */
 #ifndef OPENSSL_NO_TLSEXT
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB	53
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG	54
 #define SSL_CTRL_SET_TLSEXT_HOSTNAME		55
 #define SSL_CTRL_SET_TLSEXT_DEBUG_CB		56
 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57
 #define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59
 #define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT	60
 #define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB	61
 #define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71
 
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72
 
 #define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB	75
 #define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB		76
 #define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB		77
 
 #define SSL_CTRL_SET_SRP_ARG		78
 #define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME		79
 #define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH		80
 #define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD		81
 #ifndef OPENSSL_NO_HEARTBEATS
 #define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT				85
 #define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING		86
 #define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS	87
 #endif
 #endif
 
 #define DTLS_CTRL_GET_TIMEOUT		73
 #define DTLS_CTRL_HANDLE_TIMEOUT	74
 #define DTLS_CTRL_LISTEN			75
 
 #define SSL_CTRL_GET_RI_SUPPORT			76
 #define SSL_CTRL_CLEAR_OPTIONS			77
 #define SSL_CTRL_CLEAR_MODE			78
 
 #define SSL_CTRL_GET_EXTRA_CHAIN_CERTS		82
 #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS	83
 
 #define SSL_CTRL_CHECK_PROTO_VERSION		119
 #define DTLS_CTRL_SET_LINK_MTU			120
 #define DTLS_CTRL_GET_LINK_MIN_MTU		121
 
 #define DTLSv1_get_timeout(ssl, arg) \
 	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
 #define DTLSv1_handle_timeout(ssl) \
 	SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
 #define DTLSv1_listen(ssl, peer) \
 	SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
 
 #define SSL_session_reused(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
 #define SSL_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_clear_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_total_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
 
 #define SSL_CTX_need_tmp_RSA(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_CTX_set_tmp_rsa(ctx,rsa) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_CTX_set_tmp_dh(ctx,dh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_need_tmp_RSA(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_set_tmp_rsa(ssl,rsa) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_set_tmp_dh(ssl,dh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_set_tmp_ecdh(ssl,ecdh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_CTX_add_extra_chain_cert(ctx,x509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
 #define SSL_CTX_get_extra_chain_certs(ctx,px509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
 #define SSL_CTX_clear_extra_chain_certs(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
 
 #ifndef OPENSSL_NO_BIO
 BIO_METHOD *BIO_f_ssl(void);
 BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
 BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
 BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
 int BIO_ssl_copy_session_id(BIO *to,BIO *from);
 void BIO_ssl_shutdown(BIO *ssl_bio);
 
 #endif
 
 int	SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
 SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
 void	SSL_CTX_free(SSL_CTX *);
 long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
 long SSL_CTX_get_timeout(const SSL_CTX *ctx);
 X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
 void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
 int SSL_want(const SSL *s);
 int	SSL_clear(SSL *s);
 
 void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
 
 const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
 int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
 char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
 const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
 unsigned long 	SSL_CIPHER_get_id(const SSL_CIPHER *c);
 
 int	SSL_get_fd(const SSL *s);
 int	SSL_get_rfd(const SSL *s);
 int	SSL_get_wfd(const SSL *s);
 const char  * SSL_get_cipher_list(const SSL *s,int n);
 char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
 int	SSL_get_read_ahead(const SSL * s);
 int	SSL_pending(const SSL *s);
 #ifndef OPENSSL_NO_SOCK
 int	SSL_set_fd(SSL *s, int fd);
 int	SSL_set_rfd(SSL *s, int fd);
 int	SSL_set_wfd(SSL *s, int fd);
 #endif
 #ifndef OPENSSL_NO_BIO
 void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
 BIO *	SSL_get_rbio(const SSL *s);
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
 int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
 void	SSL_set_verify(SSL *s, int mode,
 		       int (*callback)(int ok,X509_STORE_CTX *ctx));
 void	SSL_set_verify_depth(SSL *s, int depth);
 #ifndef OPENSSL_NO_RSA
 int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
 #endif
 int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
 int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
 
 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_certificate_file(SSL *ssl, const char *file, int type);
 int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
 STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
 int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					    const char *file);
 #ifndef OPENSSL_SYS_VMS
 #ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
 int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					   const char *dir);
 #endif
 #endif
 
 #endif
 
 void	SSL_load_error_strings(void );
 const char *SSL_state_string(const SSL *s);
 const char *SSL_rstate_string(const SSL *s);
 const char *SSL_state_string_long(const SSL *s);
 const char *SSL_rstate_string_long(const SSL *s);
 long	SSL_SESSION_get_time(const SSL_SESSION *s);
 long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
 long	SSL_SESSION_get_timeout(const SSL_SESSION *s);
 long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
 void	SSL_copy_session_id(SSL *to,const SSL *from);
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
 int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
 			       unsigned int sid_ctx_len);
 
 SSL_SESSION *SSL_SESSION_new(void);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
 					unsigned int *len);
 unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
 #ifndef OPENSSL_NO_FP_API
 int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
 #endif
 #ifndef OPENSSL_NO_BIO
 int	SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
 #endif
 void	SSL_SESSION_free(SSL_SESSION *ses);
 int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
 int	SSL_set_session(SSL *to, SSL_SESSION *session);
 int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
 int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
 int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
 int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
 int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
 					unsigned int id_len);
 SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
 			     long length);
 
 #ifdef HEADER_X509_H
 X509 *	SSL_get_peer_certificate(const SSL *s);
 #endif
 
 STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
 
 int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
 int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
 int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
 void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
 			int (*callback)(int, X509_STORE_CTX *));
 void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
 void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
 #ifndef OPENSSL_NO_RSA
 int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
 #endif
 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
 int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
 	const unsigned char *d, long len);
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
 
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
 
 int SSL_CTX_check_private_key(const SSL_CTX *ctx);
 int SSL_check_private_key(const SSL *ctx);
 
 int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
 				       unsigned int sid_ctx_len);
 
 SSL *	SSL_new(SSL_CTX *ctx);
 int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
 				   unsigned int sid_ctx_len);
 
 int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
 int SSL_set_purpose(SSL *s, int purpose);
 int SSL_CTX_set_trust(SSL_CTX *s, int trust);
 int SSL_set_trust(SSL *s, int trust);
 
 int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
 int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
 
 #ifndef OPENSSL_NO_SRP
 int SSL_CTX_set_srp_username(SSL_CTX *ctx,char *name);
 int SSL_CTX_set_srp_password(SSL_CTX *ctx,char *password);
 int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
 int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
 					char *(*cb)(SSL *,void *));
 int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
 					  int (*cb)(SSL *,void *));
 int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
 				      int (*cb)(SSL *,int *,void *));
 int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
 
 int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
 			     BIGNUM *sa, BIGNUM *v, char *info);
 int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
 				const char *grp);
 
 BIGNUM *SSL_get_srp_g(SSL *s);
 BIGNUM *SSL_get_srp_N(SSL *s);
 
 char *SSL_get_srp_username(SSL *s);
 char *SSL_get_srp_userinfo(SSL *s);
 #endif
 
 void	SSL_free(SSL *ssl);
 int 	SSL_accept(SSL *ssl);
 int 	SSL_connect(SSL *ssl);
 int 	SSL_read(SSL *ssl,void *buf,int num);
 int 	SSL_peek(SSL *ssl,void *buf,int num);
 int 	SSL_write(SSL *ssl,const void *buf,int num);
 long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
 long	SSL_callback_ctrl(SSL *, int, void (*)(void));
 long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
 long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
 
 int	SSL_get_error(const SSL *s,int ret_code);
 const char *SSL_get_version(const SSL *s);
 
 /* This sets the 'default' SSL version that SSL_new() will create */
 int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
 
 #ifndef OPENSSL_NO_SSL2
 const SSL_METHOD *SSLv2_method(void);		/* SSLv2 */
 const SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */
 const SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
 #endif
 
 #ifndef OPENSSL_NO_SSL3_METHOD
 const SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
 const SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
 const SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
 #endif
 
 const SSL_METHOD *SSLv23_method(void);	/* Negotiate highest available SSL/TLS version */
 const SSL_METHOD *SSLv23_server_method(void);	/* Negotiate highest available SSL/TLS version */
 const SSL_METHOD *SSLv23_client_method(void);	/* Negotiate highest available SSL/TLS version */
 
 const SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
 const SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
 const SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
 
 const SSL_METHOD *TLSv1_1_method(void);		/* TLSv1.1 */
 const SSL_METHOD *TLSv1_1_server_method(void);	/* TLSv1.1 */
 const SSL_METHOD *TLSv1_1_client_method(void);	/* TLSv1.1 */
 
 const SSL_METHOD *TLSv1_2_method(void);		/* TLSv1.2 */
 const SSL_METHOD *TLSv1_2_server_method(void);	/* TLSv1.2 */
 const SSL_METHOD *TLSv1_2_client_method(void);	/* TLSv1.2 */
 
 
 const SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */
 const SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */
 const SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */
 
 STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
 
 int SSL_do_handshake(SSL *s);
 int SSL_renegotiate(SSL *s);
 int SSL_renegotiate_abbreviated(SSL *s);
 int SSL_renegotiate_pending(SSL *s);
 int SSL_shutdown(SSL *s);
 
 const SSL_METHOD *SSL_get_ssl_method(SSL *s);
 int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
 const char *SSL_alert_type_string_long(int value);
 const char *SSL_alert_type_string(int value);
 const char *SSL_alert_desc_string_long(int value);
 const char *SSL_alert_desc_string(int value);
 
 void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
 void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
 STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
 STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
 int SSL_add_client_CA(SSL *ssl,X509 *x);
 int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
 
 void SSL_set_connect_state(SSL *s);
 void SSL_set_accept_state(SSL *s);
 
 long SSL_get_default_timeout(const SSL *s);
 
 int SSL_library_init(void );
 
 char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
 STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
 
 SSL *SSL_dup(SSL *ssl);
 
 X509 *SSL_get_certificate(const SSL *ssl);
 /* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
 
 void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
 int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
 void SSL_set_quiet_shutdown(SSL *ssl,int mode);
 int SSL_get_quiet_shutdown(const SSL *ssl);
 void SSL_set_shutdown(SSL *ssl,int mode);
 int SSL_get_shutdown(const SSL *ssl);
 int SSL_version(const SSL *ssl);
 int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
 int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
 	const char *CApath);
 #define SSL_get0_session SSL_get_session /* just peek at pointer */
 SSL_SESSION *SSL_get_session(const SSL *ssl);
 SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
 SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
 SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
 void SSL_set_info_callback(SSL *ssl,
 			   void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
 int SSL_state(const SSL *ssl);
 void SSL_set_state(SSL *ssl, int state);
 
 void SSL_set_verify_result(SSL *ssl,long v);
 long SSL_get_verify_result(const SSL *ssl);
 
 int SSL_set_ex_data(SSL *ssl,int idx,void *data);
 void *SSL_get_ex_data(const SSL *ssl,int idx);
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
 void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
 int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_get_ex_data_X509_STORE_CTX_idx(void );
 
 #define SSL_CTX_sess_set_cache_size(ctx,t) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
 #define SSL_CTX_sess_get_cache_size(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
 #define SSL_CTX_set_session_cache_mode(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
 #define SSL_CTX_get_session_cache_mode(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
 
 #define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
 #define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
 #define SSL_CTX_get_read_ahead(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
 #define SSL_CTX_set_read_ahead(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
 #define SSL_CTX_get_max_cert_list(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_CTX_set_max_cert_list(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 #define SSL_get_max_cert_list(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_set_max_cert_list(ssl,m) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 
 #define SSL_CTX_set_max_send_fragment(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
 #define SSL_set_max_send_fragment(ssl,m) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
 
      /* NB: the keylength is only applicable when is_export is true */
 #ifndef OPENSSL_NO_RSA
 void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 
 void SSL_set_tmp_rsa_callback(SSL *ssl,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 #endif
 #ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_dh_callback(SSL *ssl,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 #ifndef OPENSSL_NO_ECDH
 void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_ecdh_callback(SSL *ssl,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 
 #ifndef OPENSSL_NO_COMP
 const COMP_METHOD *SSL_get_current_compression(SSL *s);
 const COMP_METHOD *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const COMP_METHOD *comp);
 STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
 #else
 const void *SSL_get_current_compression(SSL *s);
 const void *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const void *comp);
 void *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,void *cm);
 #endif
 
 /* TLS extensions functions */
 int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
 
 int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
 				  void *arg);
 
 /* Pre-shared secret session resumption functions */
 int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
 
 void SSL_set_debug(SSL *s, int debug);
 int SSL_cache_hit(SSL *s);
 
 #ifndef OPENSSL_NO_UNIT_TEST
 const struct openssl_ssl_test_functions *SSL_test_functions(void);
 #endif
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
 void ERR_load_SSL_strings(void);
 
 /* Error codes for the SSL functions. */
 
 /* Function codes. */
 #define SSL_F_CLIENT_CERTIFICATE			 100
 #define SSL_F_CLIENT_FINISHED				 167
 #define SSL_F_CLIENT_HELLO				 101
 #define SSL_F_CLIENT_MASTER_KEY				 102
 #define SSL_F_D2I_SSL_SESSION				 103
 #define SSL_F_DO_DTLS1_WRITE				 245
 #define SSL_F_DO_SSL3_WRITE				 104
 #define SSL_F_DTLS1_ACCEPT				 246
 #define SSL_F_DTLS1_ADD_CERT_TO_BUF			 295
 #define SSL_F_DTLS1_BUFFER_RECORD			 247
 #define SSL_F_DTLS1_CHECK_TIMEOUT_NUM			 316
 #define SSL_F_DTLS1_CLIENT_HELLO			 248
 #define SSL_F_DTLS1_CONNECT				 249
 #define SSL_F_DTLS1_ENC					 250
 #define SSL_F_DTLS1_GET_HELLO_VERIFY			 251
 #define SSL_F_DTLS1_GET_MESSAGE				 252
 #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
 #define SSL_F_DTLS1_GET_RECORD				 254
 #define SSL_F_DTLS1_HANDLE_TIMEOUT			 297
 #define SSL_F_DTLS1_HEARTBEAT				 305
 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
 #define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 288
 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
 #define SSL_F_DTLS1_PROCESS_RECORD			 257
 #define SSL_F_DTLS1_READ_BYTES				 258
 #define SSL_F_DTLS1_READ_FAILED				 259
 #define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260
 #define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261
 #define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262
 #define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263
 #define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264
 #define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265
 #define SSL_F_DTLS1_SEND_SERVER_HELLO			 266
 #define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267
 #define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268
 #define SSL_F_GET_CLIENT_FINISHED			 105
 #define SSL_F_GET_CLIENT_HELLO				 106
 #define SSL_F_GET_CLIENT_MASTER_KEY			 107
 #define SSL_F_GET_SERVER_FINISHED			 108
 #define SSL_F_GET_SERVER_HELLO				 109
 #define SSL_F_GET_SERVER_VERIFY				 110
 #define SSL_F_I2D_SSL_SESSION				 111
 #define SSL_F_READ_N					 112
 #define SSL_F_REQUEST_CERTIFICATE			 113
 #define SSL_F_SERVER_FINISH				 239
 #define SSL_F_SERVER_HELLO				 114
 #define SSL_F_SERVER_VERIFY				 240
 #define SSL_F_SSL23_ACCEPT				 115
 #define SSL_F_SSL23_CLIENT_HELLO			 116
 #define SSL_F_SSL23_CONNECT				 117
 #define SSL_F_SSL23_GET_CLIENT_HELLO			 118
 #define SSL_F_SSL23_GET_SERVER_HELLO			 119
 #define SSL_F_SSL23_PEEK				 237
 #define SSL_F_SSL23_READ				 120
 #define SSL_F_SSL23_WRITE				 121
 #define SSL_F_SSL2_ACCEPT				 122
 #define SSL_F_SSL2_CONNECT				 123
 #define SSL_F_SSL2_ENC_INIT				 124
 #define SSL_F_SSL2_GENERATE_KEY_MATERIAL		 241
 #define SSL_F_SSL2_PEEK					 234
 #define SSL_F_SSL2_READ					 125
 #define SSL_F_SSL2_READ_INTERNAL			 236
 #define SSL_F_SSL2_SET_CERTIFICATE			 126
 #define SSL_F_SSL2_WRITE				 127
 #define SSL_F_SSL3_ACCEPT				 128
 #define SSL_F_SSL3_ADD_CERT_TO_BUF			 296
 #define SSL_F_SSL3_CALLBACK_CTRL			 233
 #define SSL_F_SSL3_CHANGE_CIPHER_STATE			 129
 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM		 130
 #define SSL_F_SSL3_CHECK_CLIENT_HELLO			 304
 #define SSL_F_SSL3_CLIENT_HELLO				 131
 #define SSL_F_SSL3_CONNECT				 132
 #define SSL_F_SSL3_CTRL					 213
 #define SSL_F_SSL3_CTX_CTRL				 133
 #define SSL_F_SSL3_DIGEST_CACHED_RECORDS		 293
 #define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 292
 #define SSL_F_SSL3_ENC					 134
 #define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
 #define SSL_F_SSL3_GET_CERT_STATUS			 289
 #define SSL_F_SSL3_GET_CERT_VERIFY			 136
 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
 #define SSL_F_SSL3_GET_CLIENT_HELLO			 138
 #define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE		 139
 #define SSL_F_SSL3_GET_FINISHED				 140
 #define SSL_F_SSL3_GET_KEY_EXCHANGE			 141
 #define SSL_F_SSL3_GET_MESSAGE				 142
 #define SSL_F_SSL3_GET_NEW_SESSION_TICKET		 283
 #define SSL_F_SSL3_GET_NEXT_PROTO			 306
 #define SSL_F_SSL3_GET_RECORD				 143
 #define SSL_F_SSL3_GET_SERVER_CERTIFICATE		 144
 #define SSL_F_SSL3_GET_SERVER_DONE			 145
 #define SSL_F_SSL3_GET_SERVER_HELLO			 146
 #define SSL_F_SSL3_HANDSHAKE_MAC			 285
 #define SSL_F_SSL3_NEW_SESSION_TICKET			 287
 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147
 #define SSL_F_SSL3_PEEK					 235
 #define SSL_F_SSL3_READ_BYTES				 148
 #define SSL_F_SSL3_READ_N				 149
 #define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST		 150
 #define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE		 151
 #define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE		 152
 #define SSL_F_SSL3_SEND_CLIENT_VERIFY			 153
 #define SSL_F_SSL3_SEND_SERVER_CERTIFICATE		 154
 #define SSL_F_SSL3_SEND_SERVER_HELLO			 242
 #define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155
 #define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
 #define SSL_F_SSL3_SETUP_READ_BUFFER			 156
 #define SSL_F_SSL3_SETUP_WRITE_BUFFER			 291
 #define SSL_F_SSL3_WRITE_BYTES				 158
 #define SSL_F_SSL3_WRITE_PENDING			 159
 #define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 298
 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 277
 #define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT		 307
 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215
 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216
 #define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT	 299
 #define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 278
 #define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT		 308
 #define SSL_F_SSL_BAD_METHOD				 160
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
 #define SSL_F_SSL_CERT_DUP				 221
 #define SSL_F_SSL_CERT_INST				 222
 #define SSL_F_SSL_CERT_INSTANTIATE			 214
 #define SSL_F_SSL_CERT_NEW				 162
 #define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
 #define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 280
 #define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG		 279
 #define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230
 #define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231
 #define SSL_F_SSL_CLEAR					 164
 #define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165
 #define SSL_F_SSL_CREATE_CIPHER_LIST			 166
 #define SSL_F_SSL_CTRL					 232
 #define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
 #define SSL_F_SSL_CTX_MAKE_PROFILES			 309
 #define SSL_F_SSL_CTX_NEW				 169
 #define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
 #define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 290
 #define SSL_F_SSL_CTX_SET_PURPOSE			 226
 #define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
 #define SSL_F_SSL_CTX_SET_TRUST				 229
 #define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
 #define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT		 272
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
 #define SSL_F_SSL_DO_HANDSHAKE				 180
 #define SSL_F_SSL_GET_NEW_SESSION			 181
 #define SSL_F_SSL_GET_PREV_SESSION			 217
 #define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
 #define SSL_F_SSL_GET_SERVER_SEND_PKEY			 317
 #define SSL_F_SSL_GET_SIGN_PKEY				 183
 #define SSL_F_SSL_INIT_WBIO_BUFFER			 184
 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
 #define SSL_F_SSL_NEW					 186
 #define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 300
 #define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 302
 #define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT	 310
 #define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 301
 #define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 303
 #define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT	 311
 #define SSL_F_SSL_PEEK					 270
 #define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 281
 #define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 282
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
 #define SSL_F_SSL_SESS_CERT_NEW				 225
 #define SSL_F_SSL_SET_CERT				 191
 #define SSL_F_SSL_SET_CIPHER_LIST			 271
 #define SSL_F_SSL_SET_FD				 192
 #define SSL_F_SSL_SET_PKEY				 193
 #define SSL_F_SSL_SET_PURPOSE				 227
 #define SSL_F_SSL_SET_RFD				 194
 #define SSL_F_SSL_SET_SESSION				 195
 #define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
 #define SSL_F_SSL_SET_SESSION_TICKET_EXT		 294
 #define SSL_F_SSL_SET_TRUST				 228
 #define SSL_F_SSL_SET_WFD				 196
 #define SSL_F_SSL_SHUTDOWN				 224
 #define SSL_F_SSL_SRP_CTX_INIT				 313
 #define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
 #define SSL_F_SSL_UNDEFINED_FUNCTION			 197
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
 #define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
 #define SSL_F_SSL_USE_PSK_IDENTITY_HINT			 273
 #define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
 #define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
 #define SSL_F_SSL_WRITE					 208
 #define SSL_F_TLS1_CERT_VERIFY_MAC			 286
 #define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
 #define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
 #define SSL_F_TLS1_ENC					 210
 #define SSL_F_TLS1_EXPORT_KEYING_MATERIAL		 314
 #define SSL_F_TLS1_HEARTBEAT				 315
 #define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275
 #define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT		 276
 #define SSL_F_TLS1_PRF					 284
 #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
 #define SSL_F_WRITE_PENDING				 212
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
 #define SSL_R_BAD_ALERT_RECORD				 101
 #define SSL_R_BAD_AUTHENTICATION_TYPE			 102
 #define SSL_R_BAD_CHANGE_CIPHER_SPEC			 103
 #define SSL_R_BAD_CHECKSUM				 104
 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK		 106
 #define SSL_R_BAD_DECOMPRESSION				 107
 #define SSL_R_BAD_DH_G_LENGTH				 108
 #define SSL_R_BAD_DH_PUB_KEY_LENGTH			 109
 #define SSL_R_BAD_DH_P_LENGTH				 110
 #define SSL_R_BAD_DIGEST_LENGTH				 111
 #define SSL_R_BAD_DSA_SIGNATURE				 112
 #define SSL_R_BAD_ECC_CERT				 304
 #define SSL_R_BAD_ECDSA_SIGNATURE			 305
 #define SSL_R_BAD_ECPOINT				 306
 #define SSL_R_BAD_HANDSHAKE_LENGTH			 332
 #define SSL_R_BAD_HELLO_REQUEST				 105
 #define SSL_R_BAD_LENGTH				 271
 #define SSL_R_BAD_MAC_DECODE				 113
 #define SSL_R_BAD_MAC_LENGTH				 333
 #define SSL_R_BAD_MESSAGE_TYPE				 114
 #define SSL_R_BAD_PACKET_LENGTH				 115
 #define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116
 #define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH		 316
 #define SSL_R_BAD_RESPONSE_ARGUMENT			 117
 #define SSL_R_BAD_RSA_DECRYPT				 118
 #define SSL_R_BAD_RSA_ENCRYPT				 119
 #define SSL_R_BAD_RSA_E_LENGTH				 120
 #define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
 #define SSL_R_BAD_RSA_SIGNATURE				 122
 #define SSL_R_BAD_SIGNATURE				 123
 #define SSL_R_BAD_SRP_A_LENGTH				 347
 #define SSL_R_BAD_SRP_B_LENGTH				 348
 #define SSL_R_BAD_SRP_G_LENGTH				 349
 #define SSL_R_BAD_SRP_N_LENGTH				 350
 #define SSL_R_BAD_SRP_PARAMETERS			 371
 #define SSL_R_BAD_SRP_S_LENGTH				 351
 #define SSL_R_BAD_SRTP_MKI_VALUE			 352
 #define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST		 353
 #define SSL_R_BAD_SSL_FILETYPE				 124
 #define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
 #define SSL_R_BAD_STATE					 126
 #define SSL_R_BAD_WRITE_RETRY				 127
 #define SSL_R_BIO_NOT_SET				 128
 #define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
 #define SSL_R_BN_LIB					 130
 #define SSL_R_CA_DN_LENGTH_MISMATCH			 131
 #define SSL_R_CA_DN_TOO_LONG				 132
 #define SSL_R_CCS_RECEIVED_EARLY			 133
 #define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
 #define SSL_R_CERT_LENGTH_MISMATCH			 135
 #define SSL_R_CHALLENGE_IS_DIFFERENT			 136
 #define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
 #define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
 #define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
 #define SSL_R_CLIENTHELLO_TLSEXT			 226
 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
 #define SSL_R_COMPRESSION_DISABLED			 343
 #define SSL_R_COMPRESSION_FAILURE			 141
 #define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307
 #define SSL_R_COMPRESSION_LIBRARY_ERROR			 142
 #define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143
 #define SSL_R_CONNECTION_TYPE_NOT_SET			 144
 #define SSL_R_COOKIE_MISMATCH				 308
 #define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145
 #define SSL_R_DATA_LENGTH_TOO_LONG			 146
 #define SSL_R_DECRYPTION_FAILED				 147
 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281
+#define SSL_R_DH_KEY_TOO_SMALL				 372
 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148
 #define SSL_R_DIGEST_CHECK_FAILED			 149
 #define SSL_R_DTLS_MESSAGE_TOO_BIG			 334
 #define SSL_R_DUPLICATE_COMPRESSION_ID			 309
 #define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT		 317
 #define SSL_R_ECC_CERT_NOT_FOR_SIGNING			 318
 #define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE	 322
 #define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE	 323
 #define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310
 #define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST	 354
 #define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150
 #define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282
 #define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151
 #define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152
 #define SSL_R_EXTRA_DATA_IN_MESSAGE			 153
 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154
 #define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS		 355
 #define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION		 356
 #define SSL_R_HTTPS_PROXY_REQUEST			 155
 #define SSL_R_HTTP_REQUEST				 156
 #define SSL_R_ILLEGAL_PADDING				 283
 #define SSL_R_INAPPROPRIATE_FALLBACK			 373
 #define SSL_R_INCONSISTENT_COMPRESSION			 340
 #define SSL_R_INVALID_CHALLENGE_LENGTH			 158
 #define SSL_R_INVALID_COMMAND				 280
 #define SSL_R_INVALID_COMPRESSION_ALGORITHM		 341
 #define SSL_R_INVALID_PURPOSE				 278
 #define SSL_R_INVALID_SRP_USERNAME			 357
 #define SSL_R_INVALID_STATUS_RESPONSE			 328
 #define SSL_R_INVALID_TICKET_KEYS_LENGTH		 325
 #define SSL_R_INVALID_TRUST				 279
 #define SSL_R_KEY_ARG_TOO_LONG				 284
 #define SSL_R_KRB5					 285
 #define SSL_R_KRB5_C_CC_PRINC				 286
 #define SSL_R_KRB5_C_GET_CRED				 287
 #define SSL_R_KRB5_C_INIT				 288
 #define SSL_R_KRB5_C_MK_REQ				 289
 #define SSL_R_KRB5_S_BAD_TICKET				 290
 #define SSL_R_KRB5_S_INIT				 291
 #define SSL_R_KRB5_S_RD_REQ				 292
 #define SSL_R_KRB5_S_TKT_EXPIRED			 293
 #define SSL_R_KRB5_S_TKT_NYV				 294
 #define SSL_R_KRB5_S_TKT_SKEW				 295
 #define SSL_R_LENGTH_MISMATCH				 159
 #define SSL_R_LENGTH_TOO_SHORT				 160
 #define SSL_R_LIBRARY_BUG				 274
 #define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161
 #define SSL_R_MESSAGE_TOO_LONG				 296
 #define SSL_R_MISSING_DH_DSA_CERT			 162
 #define SSL_R_MISSING_DH_KEY				 163
 #define SSL_R_MISSING_DH_RSA_CERT			 164
 #define SSL_R_MISSING_DSA_SIGNING_CERT			 165
 #define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166
 #define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167
 #define SSL_R_MISSING_RSA_CERTIFICATE			 168
 #define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169
 #define SSL_R_MISSING_RSA_SIGNING_CERT			 170
 #define SSL_R_MISSING_SRP_PARAM				 358
 #define SSL_R_MISSING_TMP_DH_KEY			 171
 #define SSL_R_MISSING_TMP_ECDH_KEY			 311
 #define SSL_R_MISSING_TMP_RSA_KEY			 172
 #define SSL_R_MISSING_TMP_RSA_PKEY			 173
 #define SSL_R_MISSING_VERIFY_MESSAGE			 174
 #define SSL_R_MULTIPLE_SGC_RESTARTS			 346
 #define SSL_R_NON_SSLV2_INITIAL_PACKET			 175
 #define SSL_R_NO_CERTIFICATES_RETURNED			 176
 #define SSL_R_NO_CERTIFICATE_ASSIGNED			 177
 #define SSL_R_NO_CERTIFICATE_RETURNED			 178
 #define SSL_R_NO_CERTIFICATE_SET			 179
 #define SSL_R_NO_CERTIFICATE_SPECIFIED			 180
 #define SSL_R_NO_CIPHERS_AVAILABLE			 181
 #define SSL_R_NO_CIPHERS_PASSED				 182
 #define SSL_R_NO_CIPHERS_SPECIFIED			 183
 #define SSL_R_NO_CIPHER_LIST				 184
 #define SSL_R_NO_CIPHER_MATCH				 185
 #define SSL_R_NO_CLIENT_CERT_METHOD			 331
 #define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
 #define SSL_R_NO_COMPRESSION_SPECIFIED			 187
 #define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER		 330
 #define SSL_R_NO_METHOD_SPECIFIED			 188
 #define SSL_R_NO_PRIVATEKEY				 189
 #define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
 #define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
 #define SSL_R_NO_PUBLICKEY				 192
 #define SSL_R_NO_RENEGOTIATION				 339
 #define SSL_R_NO_REQUIRED_DIGEST			 324
 #define SSL_R_NO_SHARED_CIPHER				 193
 #define SSL_R_NO_SRTP_PROFILES				 359
 #define SSL_R_NO_VERIFY_CALLBACK			 194
 #define SSL_R_NULL_SSL_CTX				 195
 #define SSL_R_NULL_SSL_METHOD_PASSED			 196
 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
 #define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
 #define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG			 327
 #define SSL_R_PACKET_LENGTH_TOO_LONG			 198
 #define SSL_R_PARSE_TLSEXT				 227
 #define SSL_R_PATH_TOO_LONG				 270
 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199
 #define SSL_R_PEER_ERROR				 200
 #define SSL_R_PEER_ERROR_CERTIFICATE			 201
 #define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202
 #define SSL_R_PEER_ERROR_NO_CIPHER			 203
 #define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204
 #define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205
 #define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206
 #define SSL_R_PROTOCOL_IS_SHUTDOWN			 207
 #define SSL_R_PSK_IDENTITY_NOT_FOUND			 223
 #define SSL_R_PSK_NO_CLIENT_CB				 224
 #define SSL_R_PSK_NO_SERVER_CB				 225
 #define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208
 #define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209
 #define SSL_R_PUBLIC_KEY_NOT_RSA			 210
 #define SSL_R_READ_BIO_NOT_SET				 211
 #define SSL_R_READ_TIMEOUT_EXPIRED			 312
 #define SSL_R_READ_WRONG_PACKET_TYPE			 212
 #define SSL_R_RECORD_LENGTH_MISMATCH			 213
 #define SSL_R_RECORD_TOO_LARGE				 214
 #define SSL_R_RECORD_TOO_SMALL				 298
 #define SSL_R_RENEGOTIATE_EXT_TOO_LONG			 335
 #define SSL_R_RENEGOTIATION_ENCODING_ERR		 336
 #define SSL_R_RENEGOTIATION_MISMATCH			 337
 #define SSL_R_REQUIRED_CIPHER_MISSING			 215
 #define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING	 342
 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216
 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217
 #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218
 #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345
 #define SSL_R_SERVERHELLO_TLSEXT			 275
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
 #define SSL_R_SHORT_READ				 219
 #define SSL_R_SIGNATURE_ALGORITHMS_ERROR		 360
 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
 #define SSL_R_SRP_A_CALC				 361
 #define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES		 362
 #define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG	 363
 #define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE		 364
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
 #define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299
 #define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT		 321
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME		 319
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE		 320
 #define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300
 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222
 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE		 1042
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		 1020
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		 1045
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED		 1044
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		 1046
 #define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE		 1030
 #define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		 1040
 #define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		 1047
 #define SSL_R_SSLV3_ALERT_NO_CERTIFICATE		 1041
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
 #define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
 #define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228
 #define SSL_R_SSL_HANDSHAKE_FAILURE			 229
 #define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230
 #define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301
 #define SSL_R_SSL_SESSION_ID_CONFLICT			 302
 #define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273
 #define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303
 #define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231
 #define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049
 #define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050
 #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021
 #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051
 #define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060
 #define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK	 1086
 #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071
 #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080
 #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100
 #define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070
 #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022
 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048
 #define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE		 1114
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE	 1113
 #define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE		 1111
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112
 #define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
 #define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT		 365
 #define SSL_R_TLS_HEARTBEAT_PENDING			 366
 #define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL		 367
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 157
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
 #define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
 #define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
 #define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237
 #define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238
 #define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314
 #define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239
 #define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240
 #define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241
 #define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242
 #define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243
 #define SSL_R_UNEXPECTED_MESSAGE			 244
 #define SSL_R_UNEXPECTED_RECORD				 245
 #define SSL_R_UNINITIALIZED				 276
 #define SSL_R_UNKNOWN_ALERT_TYPE			 246
 #define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247
 #define SSL_R_UNKNOWN_CIPHER_RETURNED			 248
 #define SSL_R_UNKNOWN_CIPHER_TYPE			 249
 #define SSL_R_UNKNOWN_DIGEST				 368
 #define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250
 #define SSL_R_UNKNOWN_PKEY_TYPE				 251
 #define SSL_R_UNKNOWN_PROTOCOL				 252
 #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
 #define SSL_R_UNKNOWN_SSL_VERSION			 254
 #define SSL_R_UNKNOWN_STATE				 255
 #define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 338
 #define SSL_R_UNSUPPORTED_CIPHER			 256
 #define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
 #define SSL_R_UNSUPPORTED_DIGEST_TYPE			 326
 #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
 #define SSL_R_UNSUPPORTED_PROTOCOL			 258
 #define SSL_R_UNSUPPORTED_SSL_VERSION			 259
 #define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
 #define SSL_R_USE_SRTP_NOT_NEGOTIATED			 369
 #define SSL_R_WRITE_BIO_NOT_SET				 260
 #define SSL_R_WRONG_CIPHER_RETURNED			 261
 #define SSL_R_WRONG_MESSAGE_TYPE			 262
 #define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263
 #define SSL_R_WRONG_SIGNATURE_LENGTH			 264
 #define SSL_R_WRONG_SIGNATURE_SIZE			 265
 #define SSL_R_WRONG_SIGNATURE_TYPE			 370
 #define SSL_R_WRONG_SSL_VERSION				 266
 #define SSL_R_WRONG_VERSION_NUMBER			 267
 #define SSL_R_X509_LIB					 268
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
 
 #ifdef  __cplusplus
 }
 #endif
 #endif
Index: releng/10.1/crypto/openssl/ssl/ssl_err.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/ssl_err.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/ssl_err.c	(revision 284295)
@@ -1,613 +1,615 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
  * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 /* NOTE: this file was auto generated by the mkerr.pl script: any changes
  * made to it will be overwritten when the script next updates this file,
  * only reason strings will be preserved.
  */
 
 #include 
 #include 
 #include 
 
 /* BEGIN ERROR CODES */
 #ifndef OPENSSL_NO_ERR
 
 #define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0)
 #define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason)
 
 static ERR_STRING_DATA SSL_str_functs[]=
 	{
 {ERR_FUNC(SSL_F_CLIENT_CERTIFICATE),	"CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_CLIENT_FINISHED),	"CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_CLIENT_HELLO),	"CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_CLIENT_MASTER_KEY),	"CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_D2I_SSL_SESSION),	"d2i_SSL_SESSION"},
 {ERR_FUNC(SSL_F_DO_DTLS1_WRITE),	"DO_DTLS1_WRITE"},
 {ERR_FUNC(SSL_F_DO_SSL3_WRITE),	"DO_SSL3_WRITE"},
 {ERR_FUNC(SSL_F_DTLS1_ACCEPT),	"DTLS1_ACCEPT"},
 {ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF),	"DTLS1_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD),	"DTLS1_BUFFER_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM),	"DTLS1_CHECK_TIMEOUT_NUM"},
 {ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO),	"DTLS1_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_CONNECT),	"DTLS1_CONNECT"},
 {ERR_FUNC(SSL_F_DTLS1_ENC),	"DTLS1_ENC"},
 {ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY),	"DTLS1_GET_HELLO_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE),	"DTLS1_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT),	"DTLS1_HANDLE_TIMEOUT"},
 {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT),	"DTLS1_HEARTBEAT"},
 {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"},
 {ERR_FUNC(SSL_F_DTLS1_READ_FAILED),	"DTLS1_READ_FAILED"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST),	"DTLS1_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE),	"DTLS1_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE),	"DTLS1_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY),	"DTLS1_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),	"DTLS1_SEND_HELLO_VERIFY_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE),	"DTLS1_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO),	"DTLS1_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),	"DTLS1_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),	"DTLS1_WRITE_APP_DATA_BYTES"},
 {ERR_FUNC(SSL_F_GET_CLIENT_FINISHED),	"GET_CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_GET_CLIENT_HELLO),	"GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY),	"GET_CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_GET_SERVER_FINISHED),	"GET_SERVER_FINISHED"},
 {ERR_FUNC(SSL_F_GET_SERVER_HELLO),	"GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_GET_SERVER_VERIFY),	"GET_SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_I2D_SSL_SESSION),	"i2d_SSL_SESSION"},
 {ERR_FUNC(SSL_F_READ_N),	"READ_N"},
 {ERR_FUNC(SSL_F_REQUEST_CERTIFICATE),	"REQUEST_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SERVER_FINISH),	"SERVER_FINISH"},
 {ERR_FUNC(SSL_F_SERVER_HELLO),	"SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SERVER_VERIFY),	"SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_SSL23_ACCEPT),	"SSL23_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO),	"SSL23_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_CONNECT),	"SSL23_CONNECT"},
 {ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO),	"SSL23_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO),	"SSL23_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_PEEK),	"SSL23_PEEK"},
 {ERR_FUNC(SSL_F_SSL23_READ),	"SSL23_READ"},
 {ERR_FUNC(SSL_F_SSL23_WRITE),	"SSL23_WRITE"},
 {ERR_FUNC(SSL_F_SSL2_ACCEPT),	"SSL2_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL2_CONNECT),	"SSL2_CONNECT"},
 {ERR_FUNC(SSL_F_SSL2_ENC_INIT),	"SSL2_ENC_INIT"},
 {ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL),	"SSL2_GENERATE_KEY_MATERIAL"},
 {ERR_FUNC(SSL_F_SSL2_PEEK),	"SSL2_PEEK"},
 {ERR_FUNC(SSL_F_SSL2_READ),	"SSL2_READ"},
 {ERR_FUNC(SSL_F_SSL2_READ_INTERNAL),	"SSL2_READ_INTERNAL"},
 {ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE),	"SSL2_SET_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL2_WRITE),	"SSL2_WRITE"},
 {ERR_FUNC(SSL_F_SSL3_ACCEPT),	"SSL3_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF),	"SSL3_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),	"SSL3_CALLBACK_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),	"SSL3_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),	"SSL3_CHECK_CERT_AND_ALGORITHM"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO),	"SSL3_CHECK_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),	"SSL3_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"},
 {ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_DIGEST_CACHED_RECORDS),	"SSL3_DIGEST_CACHED_RECORDS"},
 {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"},
 {ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"},
 {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS),	"SSL3_GET_CERT_STATUS"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY),	"SSL3_GET_CERT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),	"SSL3_GET_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),	"SSL3_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE),	"SSL3_GET_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_FINISHED),	"SSL3_GET_FINISHED"},
 {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),	"SSL3_GET_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),	"SSL3_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),	"SSL3_GET_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_GET_NEXT_PROTO),	"SSL3_GET_NEXT_PROTO"},
 {ERR_FUNC(SSL_F_SSL3_GET_RECORD),	"SSL3_GET_RECORD"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),	"SSL3_GET_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE),	"SSL3_GET_SERVER_DONE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),	"SSL3_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC),	"ssl3_handshake_mac"},
 {ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),	"SSL3_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),	"SSL3_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL3_PEEK),	"SSL3_PEEK"},
 {ERR_FUNC(SSL_F_SSL3_READ_BYTES),	"SSL3_READ_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_READ_N),	"SSL3_READ_N"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST),	"SSL3_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE),	"SSL3_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY),	"SSL3_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE),	"SSL3_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO),	"SSL3_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE),	"SSL3_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK),	"SSL3_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER),	"SSL3_SETUP_READ_BUFFER"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER),	"SSL3_SETUP_WRITE_BUFFER"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT),	"SSL_ADD_CLIENTHELLO_USE_SRTP_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),	"SSL_add_dir_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),	"SSL_add_file_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"SSL_ADD_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT),	"SSL_ADD_SERVERHELLO_USE_SRTP_EXT"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"SSL_BAD_METHOD"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"SSL_BYTES_TO_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CERT_DUP),	"SSL_CERT_DUP"},
 {ERR_FUNC(SSL_F_SSL_CERT_INST),	"SSL_CERT_INST"},
 {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"},
 {ERR_FUNC(SSL_F_SSL_CERT_NEW),	"SSL_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),	"SSL_CHECK_SRVR_ECC_CERT_AND_ALG"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),	"SSL_CIPHER_PROCESS_RULESTR"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),	"SSL_CIPHER_STRENGTH_SORT"},
 {ERR_FUNC(SSL_F_SSL_CLEAR),	"SSL_clear"},
 {ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),	"SSL_COMP_add_compression_method"},
 {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST),	"SSL_CREATE_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
 {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CTX_MAKE_PROFILES),	"SSL_CTX_MAKE_PROFILES"},
 {ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),	"SSL_CTX_use_psk_identity_hint"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
 {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY),	"SSL_GET_SERVER_SEND_PKEY"},
 {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
 {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
 {ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT),	"SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT),	"SSL_PARSE_SERVERHELLO_USE_SRTP_EXT"},
 {ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),	"SSL_SESSION_set1_id_context"},
 {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_SET_CERT),	"SSL_SET_CERT"},
 {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),	"SSL_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_SET_FD),	"SSL_set_fd"},
 {ERR_FUNC(SSL_F_SSL_SET_PKEY),	"SSL_SET_PKEY"},
 {ERR_FUNC(SSL_F_SSL_SET_PURPOSE),	"SSL_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_SET_RFD),	"SSL_set_rfd"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION),	"SSL_set_session"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),	"SSL_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT),	"SSL_set_session_ticket_ext"},
 {ERR_FUNC(SSL_F_SSL_SET_TRUST),	"SSL_set_trust"},
 {ERR_FUNC(SSL_F_SSL_SET_WFD),	"SSL_set_wfd"},
 {ERR_FUNC(SSL_F_SSL_SHUTDOWN),	"SSL_shutdown"},
 {ERR_FUNC(SSL_F_SSL_SRP_CTX_INIT),	"SSL_SRP_CTX_init"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION),	"SSL_UNDEFINED_CONST_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION),	"SSL_UNDEFINED_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),	"SSL_UNDEFINED_VOID_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE),	"SSL_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1),	"SSL_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE),	"SSL_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),	"SSL_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),	"SSL_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),	"SSL_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_USE_PSK_IDENTITY_HINT),	"SSL_use_psk_identity_hint"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),	"SSL_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),	"SSL_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"SSL_VERIFY_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"},
 {ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),	"tls1_cert_verify_mac"},
 {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT),	"TLS1_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
 {ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL),	"TLS1_EXPORT_KEYING_MATERIAL"},
 {ERR_FUNC(SSL_F_TLS1_HEARTBEAT),	"SSL_F_TLS1_HEARTBEAT"},
 {ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT),	"TLS1_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT),	"TLS1_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
 {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
 {0,NULL}
 	};
 
 static ERR_STRING_DATA SSL_str_reasons[]=
 	{
 {ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"},
 {ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"},
 {ERR_REASON(SSL_R_BAD_ALERT_RECORD)      ,"bad alert record"},
 {ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"},
 {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"},
 {ERR_REASON(SSL_R_BAD_CHECKSUM)          ,"bad checksum"},
 {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),"bad data returned by callback"},
 {ERR_REASON(SSL_R_BAD_DECOMPRESSION)     ,"bad decompression"},
 {ERR_REASON(SSL_R_BAD_DH_G_LENGTH)       ,"bad dh g length"},
 {ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) ,"bad dh pub key length"},
 {ERR_REASON(SSL_R_BAD_DH_P_LENGTH)       ,"bad dh p length"},
 {ERR_REASON(SSL_R_BAD_DIGEST_LENGTH)     ,"bad digest length"},
 {ERR_REASON(SSL_R_BAD_DSA_SIGNATURE)     ,"bad dsa signature"},
 {ERR_REASON(SSL_R_BAD_ECC_CERT)          ,"bad ecc cert"},
 {ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE)   ,"bad ecdsa signature"},
 {ERR_REASON(SSL_R_BAD_ECPOINT)           ,"bad ecpoint"},
 {ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH)  ,"bad handshake length"},
 {ERR_REASON(SSL_R_BAD_HELLO_REQUEST)     ,"bad hello request"},
 {ERR_REASON(SSL_R_BAD_LENGTH)            ,"bad length"},
 {ERR_REASON(SSL_R_BAD_MAC_DECODE)        ,"bad mac decode"},
 {ERR_REASON(SSL_R_BAD_MAC_LENGTH)        ,"bad mac length"},
 {ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"},
 {ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"},
 {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"},
 {ERR_REASON(SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH),"bad psk identity hint length"},
 {ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"},
 {ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_E_LENGTH)      ,"bad rsa e length"},
 {ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH),"bad rsa modulus length"},
 {ERR_REASON(SSL_R_BAD_RSA_SIGNATURE)     ,"bad rsa signature"},
 {ERR_REASON(SSL_R_BAD_SIGNATURE)         ,"bad signature"},
 {ERR_REASON(SSL_R_BAD_SRP_A_LENGTH)      ,"bad srp a length"},
 {ERR_REASON(SSL_R_BAD_SRP_B_LENGTH)      ,"bad srp b length"},
 {ERR_REASON(SSL_R_BAD_SRP_G_LENGTH)      ,"bad srp g length"},
 {ERR_REASON(SSL_R_BAD_SRP_N_LENGTH)      ,"bad srp n length"},
 {ERR_REASON(SSL_R_BAD_SRP_PARAMETERS)    ,"bad srp parameters"},
 {ERR_REASON(SSL_R_BAD_SRP_S_LENGTH)      ,"bad srp s length"},
 {ERR_REASON(SSL_R_BAD_SRTP_MKI_VALUE)    ,"bad srtp mki value"},
 {ERR_REASON(SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST),"bad srtp protection profile list"},
 {ERR_REASON(SSL_R_BAD_SSL_FILETYPE)      ,"bad ssl filetype"},
 {ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH),"bad ssl session id length"},
 {ERR_REASON(SSL_R_BAD_STATE)             ,"bad state"},
 {ERR_REASON(SSL_R_BAD_WRITE_RETRY)       ,"bad write retry"},
 {ERR_REASON(SSL_R_BIO_NOT_SET)           ,"bio not set"},
 {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),"block cipher pad is wrong"},
 {ERR_REASON(SSL_R_BN_LIB)                ,"bn lib"},
 {ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) ,"ca dn length mismatch"},
 {ERR_REASON(SSL_R_CA_DN_TOO_LONG)        ,"ca dn too long"},
 {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY)    ,"ccs received early"},
 {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"},
 {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH)  ,"cert length mismatch"},
 {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"},
 {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
 {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
 {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
 {ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"},
 {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
 {ERR_REASON(SSL_R_COMPRESSION_DISABLED)  ,"compression disabled"},
 {ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"},
 {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
 {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),"compression library error"},
 {ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT),"connection id is different"},
 {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET),"connection type not set"},
 {ERR_REASON(SSL_R_COOKIE_MISMATCH)       ,"cookie mismatch"},
 {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),"data between ccs and finished"},
 {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG)  ,"data length too long"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED)     ,"decryption failed"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"},
+{ERR_REASON(SSL_R_DH_KEY_TOO_SMALL), "dh key too small"},
 {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"},
 {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED)   ,"digest check failed"},
 {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG)  ,"dtls message too big"},
 {ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID),"duplicate compression id"},
 {ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT),"ecc cert not for key agreement"},
 {ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_SIGNING),"ecc cert not for signing"},
 {ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE),"ecc cert should have rsa signature"},
 {ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE),"ecc cert should have sha1 signature"},
 {ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER),"ecgroup too large for cipher"},
 {ERR_REASON(SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST),"empty srtp protection profile list"},
 {ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),"encrypted length too long"},
 {ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY),"error generating tmp rsa key"},
 {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),"error in received cipher list"},
 {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"},
 {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"},
 {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"},
 {ERR_REASON(SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS),"got next proto before a ccs"},
 {ERR_REASON(SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION),"got next proto without seeing extension"},
 {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"},
 {ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"},
 {ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"},
 {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK),"inappropriate fallback"},
 {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},
 {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
 {ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"},
 {ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),"invalid compression algorithm"},
 {ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"},
 {ERR_REASON(SSL_R_INVALID_SRP_USERNAME)  ,"invalid srp username"},
 {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"},
 {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"},
 {ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"},
 {ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"},
 {ERR_REASON(SSL_R_KRB5)                  ,"krb5"},
 {ERR_REASON(SSL_R_KRB5_C_CC_PRINC)       ,"krb5 client cc principal (no tkt?)"},
 {ERR_REASON(SSL_R_KRB5_C_GET_CRED)       ,"krb5 client get cred"},
 {ERR_REASON(SSL_R_KRB5_C_INIT)           ,"krb5 client init"},
 {ERR_REASON(SSL_R_KRB5_C_MK_REQ)         ,"krb5 client mk_req (expired tkt?)"},
 {ERR_REASON(SSL_R_KRB5_S_BAD_TICKET)     ,"krb5 server bad ticket"},
 {ERR_REASON(SSL_R_KRB5_S_INIT)           ,"krb5 server init"},
 {ERR_REASON(SSL_R_KRB5_S_RD_REQ)         ,"krb5 server rd_req (keytab perms?)"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED)    ,"krb5 server tkt expired"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_NYV)        ,"krb5 server tkt not yet valid"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_SKEW)       ,"krb5 server tkt skew"},
 {ERR_REASON(SSL_R_LENGTH_MISMATCH)       ,"length mismatch"},
 {ERR_REASON(SSL_R_LENGTH_TOO_SHORT)      ,"length too short"},
 {ERR_REASON(SSL_R_LIBRARY_BUG)           ,"library bug"},
 {ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS),"library has no ciphers"},
 {ERR_REASON(SSL_R_MESSAGE_TOO_LONG)      ,"message too long"},
 {ERR_REASON(SSL_R_MISSING_DH_DSA_CERT)   ,"missing dh dsa cert"},
 {ERR_REASON(SSL_R_MISSING_DH_KEY)        ,"missing dh key"},
 {ERR_REASON(SSL_R_MISSING_DH_RSA_CERT)   ,"missing dh rsa cert"},
 {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT),"missing dsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY),"missing export tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY),"missing export tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE),"missing rsa certificate"},
 {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),"missing rsa encrypting cert"},
 {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT),"missing rsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_SRP_PARAM)     ,"can't find SRP server param"},
 {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY)    ,"missing tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY)  ,"missing tmp ecdh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"},
 {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
 {ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"},
 {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
 {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED),"no certificate returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SET)    ,"no certificate set"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED),"no certificate specified"},
 {ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE)  ,"no ciphers available"},
 {ERR_REASON(SSL_R_NO_CIPHERS_PASSED)     ,"no ciphers passed"},
 {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"},
 {ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"},
 {ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"},
 {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"},
 {ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),"Peer haven't sent GOST certificate, required for selected ciphersuite"},
 {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"},
 {ERR_REASON(SSL_R_NO_PRIVATEKEY)         ,"no privatekey"},
 {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"},
 {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"},
 {ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"},
 {ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST)    ,"digest requred for handshake isn't computed"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
 {ERR_REASON(SSL_R_NO_SRTP_PROFILES)      ,"no srtp profiles"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
 {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
 {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
 {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"},
 {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
 {ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"},
 {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
 {ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"},
 {ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"},
 {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"},
 {ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE),"peer error certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE),"peer error no certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER)  ,"peer error no cipher"},
 {ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE),"peer error unsupported certificate type"},
 {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"},
 {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"},
 {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"},
 {ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND),"psk identity not found"},
 {ERR_REASON(SSL_R_PSK_NO_CLIENT_CB)      ,"psk no client cb"},
 {ERR_REASON(SSL_R_PSK_NO_SERVER_CB)      ,"psk no server cb"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
 {ERR_REASON(SSL_R_READ_BIO_NOT_SET)      ,"read bio not set"},
 {ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED)  ,"read timeout expired"},
 {ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE),"read wrong packet type"},
 {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"},
 {ERR_REASON(SSL_R_RECORD_TOO_LARGE)      ,"record too large"},
 {ERR_REASON(SSL_R_RECORD_TOO_SMALL)      ,"record too small"},
 {ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"},
 {ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"},
 {ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"},
 {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"},
 {ERR_REASON(SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING),"required compresssion algorithm missing"},
 {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
 {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
 {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
 {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
 {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
 {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
 {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
 {ERR_REASON(SSL_R_SIGNATURE_ALGORITHMS_ERROR),"signature algorithms error"},
 {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
 {ERR_REASON(SSL_R_SRP_A_CALC)            ,"error with the srp params"},
 {ERR_REASON(SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES),"srtp could not allocate profiles"},
 {ERR_REASON(SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG),"srtp protection profile list too long"},
 {ERR_REASON(SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE),"srtp unknown protection profile"},
 {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
 {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT),"ssl3 ext invalid ecpointformat"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),"sslv3 alert bad record mac"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),"sslv3 alert certificate expired"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),"sslv3 alert certificate revoked"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),"sslv3 alert certificate unknown"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),"sslv3 alert decompression failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),"sslv3 alert handshake failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),"sslv3 alert illegal parameter"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),"sslv3 alert no certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),"sslv3 alert unexpected message"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),"sslv3 alert unsupported certificate"},
 {ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),"ssl ctx has no default ssl version"},
 {ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) ,"ssl handshake failure"},
 {ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),"ssl library has no ciphers"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),"ssl session id callback failed"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT),"ssl session id conflict"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),"ssl session id context too long"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),"ssl session id has bad length"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT),"ssl session id is different"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),"tlsv1 alert access denied"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR),"tlsv1 alert decode error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),"tlsv1 alert inappropriate fallback"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),"tlsv1 alert protocol version"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"},
 {ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"},
 {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
 {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
 {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
 {ERR_REASON(SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT),"peer does not accept heartbeats"},
 {ERR_REASON(SSL_R_TLS_HEARTBEAT_PENDING) ,"heartbeat request already pending"},
 {ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL),"tls illegal exporter label"},
 {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
 {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY),"unable to extract public key"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS),"unable to find dh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),"unable to find ecdh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),"unable to find public key parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD),"unable to find ssl method"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES),"unable to load ssl2 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),"unable to load ssl3 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),"unable to load ssl3 sha1 routines"},
 {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE)    ,"unexpected message"},
 {ERR_REASON(SSL_R_UNEXPECTED_RECORD)     ,"unexpected record"},
 {ERR_REASON(SSL_R_UNINITIALIZED)         ,"uninitialized"},
 {ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE)    ,"unknown alert type"},
 {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"},
 {ERR_REASON(SSL_R_UNKNOWN_DIGEST)        ,"unknown digest"},
 {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"},
 {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"},
 {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"},
 {ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"},
 {ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION)   ,"unknown ssl version"},
 {ERR_REASON(SSL_R_UNKNOWN_STATE)         ,"unknown state"},
 {ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"},
 {ERR_REASON(SSL_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
 {ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
 {ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE),"unsupported digest type"},
 {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"},
 {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"},
 {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"},
 {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
 {ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED),"use srtp not negotiated"},
 {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
 {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
 {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
 {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_TYPE)  ,"wrong signature type"},
 {ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"},
 {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
 {ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
 {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
 {0,NULL}
 	};
 
 #endif
 
 void ERR_load_SSL_strings(void)
 	{
 #ifndef OPENSSL_NO_ERR
 
 	if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
 		{
 		ERR_load_strings(0,SSL_str_functs);
 		ERR_load_strings(0,SSL_str_reasons);
 		}
 #endif
 	}
Index: releng/10.1/crypto/openssl/ssl/ssl_locl.h
===================================================================
--- releng/10.1/crypto/openssl/ssl/ssl_locl.h	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/ssl_locl.h	(revision 284295)
@@ -1,1199 +1,1200 @@
 /* ssl/ssl_locl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 /* ====================================================================
  * Copyright 2005 Nokia. All rights reserved.
  *
  * The portions of the attached software ("Contribution") is developed by
  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
  * license.
  *
  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
  * support (see RFC 4279) to OpenSSL.
  *
  * No patent licenses or other rights except those expressly stated in
  * the OpenSSL open source license shall be deemed granted or received
  * expressly, by implication, estoppel, or otherwise.
  *
  * No assurances are provided by Nokia that the Contribution does not
  * infringe the patent or other intellectual property rights of any third
  * party or that the license provides you with all the necessary rights
  * to make use of the Contribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
 
 #ifndef HEADER_SSL_LOCL_H
 #define HEADER_SSL_LOCL_H
 #include 
 #include 
 #include 
 #include 
 
 #include "e_os.h"
 
 #include 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #include 
 #include 
 #ifndef OPENSSL_NO_RSA
 #include 
 #endif
 #ifndef OPENSSL_NO_DSA
 #include 
 #endif
 #include 
 #include 
 #include 
 
 #ifdef OPENSSL_BUILD_SHLIBSSL
 # undef OPENSSL_EXTERN
 # define OPENSSL_EXTERN OPENSSL_EXPORT
 #endif
 
 #undef PKCS1_CHECK
 
 #define c2l(c,l)	(l = ((unsigned long)(*((c)++)))     , \
 			 l|=(((unsigned long)(*((c)++)))<< 8), \
 			 l|=(((unsigned long)(*((c)++)))<<16), \
 			 l|=(((unsigned long)(*((c)++)))<<24))
 
 /* NOTE - c is not incremented as per c2l */
 #define c2ln(c,l1,l2,n)	{ \
 			c+=n; \
 			l1=l2=0; \
 			switch (n) { \
 			case 8: l2 =((unsigned long)(*(--(c))))<<24; \
 			case 7: l2|=((unsigned long)(*(--(c))))<<16; \
 			case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
 			case 5: l2|=((unsigned long)(*(--(c))));     \
 			case 4: l1 =((unsigned long)(*(--(c))))<<24; \
 			case 3: l1|=((unsigned long)(*(--(c))))<<16; \
 			case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
 			case 1: l1|=((unsigned long)(*(--(c))));     \
 				} \
 			}
 
 #define l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff))
 
 #define n2l(c,l)	(l =((unsigned long)(*((c)++)))<<24, \
 			 l|=((unsigned long)(*((c)++)))<<16, \
 			 l|=((unsigned long)(*((c)++)))<< 8, \
 			 l|=((unsigned long)(*((c)++))))
 
 #define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n6(l,c)	(*((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n8(l,c)	(*((c)++)=(unsigned char)(((l)>>56)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>48)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define n2l6(c,l)	(l =((BN_ULLONG)(*((c)++)))<<40, \
 			 l|=((BN_ULLONG)(*((c)++)))<<32, \
 			 l|=((BN_ULLONG)(*((c)++)))<<24, \
 			 l|=((BN_ULLONG)(*((c)++)))<<16, \
 			 l|=((BN_ULLONG)(*((c)++)))<< 8, \
 			 l|=((BN_ULLONG)(*((c)++))))
 
 /* NOTE - c is not incremented as per l2c */
 #define l2cn(l1,l2,c,n)	{ \
 			c+=n; \
 			switch (n) { \
 			case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
 			case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
 			case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
 			case 5: *(--(c))=(unsigned char)(((l2)    )&0xff); \
 			case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
 			case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
 			case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
 			case 1: *(--(c))=(unsigned char)(((l1)    )&0xff); \
 				} \
 			}
 
 #define n2s(c,s)	((s=(((unsigned int)(c[0]))<< 8)| \
 			    (((unsigned int)(c[1]))    )),c+=2)
 #define s2n(s,c)	((c[0]=(unsigned char)(((s)>> 8)&0xff), \
 			  c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
 
 #define n2l3(c,l)	((l =(((unsigned long)(c[0]))<<16)| \
 			     (((unsigned long)(c[1]))<< 8)| \
 			     (((unsigned long)(c[2]))    )),c+=3)
 
 #define l2n3(l,c)	((c[0]=(unsigned char)(((l)>>16)&0xff), \
 			  c[1]=(unsigned char)(((l)>> 8)&0xff), \
 			  c[2]=(unsigned char)(((l)    )&0xff)),c+=3)
 
 /* LOCAL STUFF */
 
 #define SSL_DECRYPT	0
 #define SSL_ENCRYPT	1
 
 #define TWO_BYTE_BIT	0x80
 #define SEC_ESC_BIT	0x40
 #define TWO_BYTE_MASK	0x7fff
 #define THREE_BYTE_MASK	0x3fff
 
 #define INC32(a)	((a)=((a)+1)&0xffffffffL)
 #define DEC32(a)	((a)=((a)-1)&0xffffffffL)
 #define MAX_MAC_SIZE	20 /* up from 16 for SSLv3 */
 
 /*
  * Define the Bitmasks for SSL_CIPHER.algorithms.
  * This bits are used packed as dense as possible. If new methods/ciphers
  * etc will be added, the bits a likely to change, so this information
  * is for internal library use only, even though SSL_CIPHER.algorithms
  * can be publicly accessed.
  * Use the according functions for cipher management instead.
  *
  * The bit mask handling in the selection and sorting scheme in
  * ssl_create_cipher_list() has only limited capabilities, reflecting
  * that the different entities within are mutually exclusive:
  * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
  */
 
 /* Bits for algorithm_mkey (key exchange algorithm) */
 #define SSL_kRSA		0x00000001L /* RSA key exchange */
 #define SSL_kDHr		0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */
 #define SSL_kDHd		0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */
 #define SSL_kEDH		0x00000008L /* tmp DH key no DH cert */
 #define SSL_kKRB5		0x00000010L /* Kerberos5 key exchange */
 #define SSL_kECDHr		0x00000020L /* ECDH cert, RSA CA cert */
 #define SSL_kECDHe		0x00000040L /* ECDH cert, ECDSA CA cert */
 #define SSL_kEECDH		0x00000080L /* ephemeral ECDH */
 #define SSL_kPSK		0x00000100L /* PSK */
 #define SSL_kGOST       0x00000200L /* GOST key exchange */
 #define SSL_kSRP        0x00000400L /* SRP */
 
 /* Bits for algorithm_auth (server authentication) */
 #define SSL_aRSA		0x00000001L /* RSA auth */
 #define SSL_aDSS 		0x00000002L /* DSS auth */
 #define SSL_aNULL 		0x00000004L /* no auth (i.e. use ADH or AECDH) */
 #define SSL_aDH 		0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */
 #define SSL_aECDH 		0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */
 #define SSL_aKRB5               0x00000020L /* KRB5 auth */
 #define SSL_aECDSA              0x00000040L /* ECDSA auth*/
 #define SSL_aPSK                0x00000080L /* PSK auth */
 #define SSL_aGOST94				0x00000100L /* GOST R 34.10-94 signature auth */
 #define SSL_aGOST01 			0x00000200L /* GOST R 34.10-2001 signature auth */
 #define SSL_aSRP 		0x00000400L /* SRP auth */
 
 
 /* Bits for algorithm_enc (symmetric encryption) */
 #define SSL_DES			0x00000001L
 #define SSL_3DES		0x00000002L
 #define SSL_RC4			0x00000004L
 #define SSL_RC2			0x00000008L
 #define SSL_IDEA		0x00000010L
 #define SSL_eNULL		0x00000020L
 #define SSL_AES128		0x00000040L
 #define SSL_AES256		0x00000080L
 #define SSL_CAMELLIA128		0x00000100L
 #define SSL_CAMELLIA256		0x00000200L
 #define SSL_eGOST2814789CNT	0x00000400L
 #define SSL_SEED		0x00000800L
 #define SSL_AES128GCM		0x00001000L
 #define SSL_AES256GCM		0x00002000L
 
 #define SSL_AES        		(SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
 #define SSL_CAMELLIA		(SSL_CAMELLIA128|SSL_CAMELLIA256)
 
 
 /* Bits for algorithm_mac (symmetric authentication) */
 
 #define SSL_MD5			0x00000001L
 #define SSL_SHA1		0x00000002L
 #define SSL_GOST94      0x00000004L
 #define SSL_GOST89MAC   0x00000008L
 #define SSL_SHA256		0x00000010L
 #define SSL_SHA384		0x00000020L
 /* Not a real MAC, just an indication it is part of cipher */
 #define SSL_AEAD		0x00000040L
 
 /* Bits for algorithm_ssl (protocol version) */
 #define SSL_SSLV2		0x00000001L
 #define SSL_SSLV3		0x00000002L
 #define SSL_TLSV1		SSL_SSLV3	/* for now */
 #define SSL_TLSV1_2		0x00000004L
 
 
 /* Bits for algorithm2 (handshake digests and other extra flags) */
 
 #define SSL_HANDSHAKE_MAC_MD5 0x10
 #define SSL_HANDSHAKE_MAC_SHA 0x20
 #define SSL_HANDSHAKE_MAC_GOST94 0x40
 #define SSL_HANDSHAKE_MAC_SHA256 0x80
 #define SSL_HANDSHAKE_MAC_SHA384 0x100
 #define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA)
 
 /* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX
  * make sure to update this constant too */
 #define SSL_MAX_DIGEST 6
 
 #define TLS1_PRF_DGST_MASK	(0xff << TLS1_PRF_DGST_SHIFT)
 
 #define TLS1_PRF_DGST_SHIFT 10
 #define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT)
 #define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT)
 #define TLS1_PRF_SHA256 (SSL_HANDSHAKE_MAC_SHA256 << TLS1_PRF_DGST_SHIFT)
 #define TLS1_PRF_SHA384 (SSL_HANDSHAKE_MAC_SHA384 << TLS1_PRF_DGST_SHIFT)
 #define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT)
 #define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1)
 
 /* Stream MAC for GOST ciphersuites from cryptopro draft
  * (currently this also goes into algorithm2) */
 #define TLS1_STREAM_MAC 0x04
 
 
 
 /*
  * Export and cipher strength information. For each cipher we have to decide
  * whether it is exportable or not. This information is likely to change
  * over time, since the export control rules are no static technical issue.
  *
  * Independent of the export flag the cipher strength is sorted into classes.
  * SSL_EXP40 was denoting the 40bit US export limit of past times, which now
  * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change
  * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more,
  * since SSL_EXP64 could be similar to SSL_LOW.
  * For this reason SSL_MICRO and SSL_MINI macros are included to widen the
  * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed
  * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would
  * be possible.
  */
 #define SSL_EXP_MASK		0x00000003L
 #define SSL_STRONG_MASK		0x000001fcL
 
 #define SSL_NOT_EXP		0x00000001L
 #define SSL_EXPORT		0x00000002L
 
 #define SSL_STRONG_NONE		0x00000004L
 #define SSL_EXP40		0x00000008L
 #define SSL_MICRO		(SSL_EXP40)
 #define SSL_EXP56		0x00000010L
 #define SSL_MINI		(SSL_EXP56)
 #define SSL_LOW			0x00000020L
 #define SSL_MEDIUM		0x00000040L
 #define SSL_HIGH		0x00000080L
 #define SSL_FIPS		0x00000100L
 
 /* we have used 000001ff - 23 bits left to go */
 
 /*
  * Macros to check the export status and cipher strength for export ciphers.
  * Even though the macros for EXPORT and EXPORT40/56 have similar names,
  * their meaning is different:
  * *_EXPORT macros check the 'exportable' status.
  * *_EXPORT40/56 macros are used to check whether a certain cipher strength
  *          is given.
  * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct
  * algorithm structure element to be passed (algorithms, algo_strength) and no
  * typechecking can be done as they are all of type unsigned long, their
  * direct usage is discouraged.
  * Use the SSL_C_* macros instead.
  */
 #define SSL_IS_EXPORT(a)	((a)&SSL_EXPORT)
 #define SSL_IS_EXPORT56(a)	((a)&SSL_EXP56)
 #define SSL_IS_EXPORT40(a)	((a)&SSL_EXP40)
 #define SSL_C_IS_EXPORT(c)	SSL_IS_EXPORT((c)->algo_strength)
 #define SSL_C_IS_EXPORT56(c)	SSL_IS_EXPORT56((c)->algo_strength)
 #define SSL_C_IS_EXPORT40(c)	SSL_IS_EXPORT40((c)->algo_strength)
 
 #define SSL_EXPORT_KEYLENGTH(a,s)	(SSL_IS_EXPORT40(s) ? 5 : \
 				 (a) == SSL_DES ? 8 : 7)
 #define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024)
 #define SSL_C_EXPORT_KEYLENGTH(c)	SSL_EXPORT_KEYLENGTH((c)->algorithm_enc, \
 				(c)->algo_strength)
 #define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
 
 
 
 
 /* Mostly for SSLv3 */
 #define SSL_PKEY_RSA_ENC	0
 #define SSL_PKEY_RSA_SIGN	1
 #define SSL_PKEY_DSA_SIGN	2
 #define SSL_PKEY_DH_RSA		3
 #define SSL_PKEY_DH_DSA		4
 #define SSL_PKEY_ECC            5
 #define SSL_PKEY_GOST94		6
 #define SSL_PKEY_GOST01		7
 #define SSL_PKEY_NUM		8
 
 /* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) |
  * 	    <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN)
  * SSL_kDH  <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
  * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN
  * SSL_aRSA <- RSA_ENC | RSA_SIGN
  * SSL_aDSS <- DSA_SIGN
  */
 
 /*
 #define CERT_INVALID		0
 #define CERT_PUBLIC_KEY		1
 #define CERT_PRIVATE_KEY	2
 */
 
 #ifndef OPENSSL_NO_EC
 /* From ECC-TLS draft, used in encoding the curve type in 
  * ECParameters
  */
 #define EXPLICIT_PRIME_CURVE_TYPE  1   
 #define EXPLICIT_CHAR2_CURVE_TYPE  2
 #define NAMED_CURVE_TYPE           3
 #endif  /* OPENSSL_NO_EC */
 
 typedef struct cert_pkey_st
 	{
 	X509 *x509;
 	EVP_PKEY *privatekey;
 	/* Digest to use when signing */
 	const EVP_MD *digest;
 	} CERT_PKEY;
 
 typedef struct cert_st
 	{
 	/* Current active set */
 	CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
 			 * Probably it would make more sense to store
 			 * an index, not a pointer. */
  
 	/* The following masks are for the key and auth
 	 * algorithms that are supported by the certs below */
 	int valid;
 	unsigned long mask_k;
 	unsigned long mask_a;
 	unsigned long export_mask_k;
 	unsigned long export_mask_a;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa_tmp;
 	RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh_tmp;
 	DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh_tmp;
 	/* Callback for generating ephemeral ECDH keys */
 	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 
 	CERT_PKEY pkeys[SSL_PKEY_NUM];
 
 	int references; /* >1 only if SSL_copy_session_id is used */
 	} CERT;
 
 
 typedef struct sess_cert_st
 	{
 	STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */
 
 	/* The 'peer_...' members are used only by clients. */
 	int peer_cert_type;
 
 	CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */
 	CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
 	/* Obviously we don't have the private keys of these,
 	 * so maybe we shouldn't even use the CERT_PKEY type here. */
 
 #ifndef OPENSSL_NO_RSA
 	RSA *peer_rsa_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *peer_dh_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *peer_ecdh_tmp;
 #endif
 
 	int references; /* actually always 1 at the moment */
 	} SESS_CERT;
 
 
 /*#define MAC_DEBUG	*/
 
 /*#define ERR_DEBUG	*/
 /*#define ABORT_DEBUG	*/
 /*#define PKT_DEBUG 1   */
 /*#define DES_DEBUG	*/
 /*#define DES_OFB_DEBUG	*/
 /*#define SSL_DEBUG	*/
 /*#define RSA_DEBUG	*/ 
 /*#define IDEA_DEBUG	*/ 
 
 #define FP_ICC  (int (*)(const void *,const void *))
 #define ssl_put_cipher_by_char(ssl,ciph,ptr) \
 		((ssl)->method->put_cipher_by_char((ciph),(ptr)))
 #define ssl_get_cipher_by_char(ssl,ptr) \
 		((ssl)->method->get_cipher_by_char(ptr))
 
 /* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff
  * It is a bit of a mess of functions, but hell, think of it as
  * an opaque structure :-) */
 typedef struct ssl3_enc_method
 	{
 	int (*enc)(SSL *, int);
 	int (*mac)(SSL *, unsigned char *, int);
 	int (*setup_key_block)(SSL *);
 	int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int);
 	int (*change_cipher_state)(SSL *, int);
 	int (*final_finish_mac)(SSL *,  const char *, int, unsigned char *);
 	int finish_mac_length;
 	int (*cert_verify_mac)(SSL *, int, unsigned char *);
 	const char *client_finished_label;
 	int client_finished_label_len;
 	const char *server_finished_label;
 	int server_finished_label_len;
 	int (*alert_value)(int);
 	int (*export_keying_material)(SSL *, unsigned char *, size_t,
 				      const char *, size_t,
 				      const unsigned char *, size_t,
 				      int use_context);
 	} SSL3_ENC_METHOD;
 
 #ifndef OPENSSL_NO_COMP
 /* Used for holding the relevant compression methods loaded into SSL_CTX */
 typedef struct ssl3_comp_st
 	{
 	int comp_id;	/* The identifier byte for this compression type */
 	char *name;	/* Text name used for the compression type */
 	COMP_METHOD *method; /* The method :-) */
 	} SSL3_COMP;
 #endif
 
 #ifndef OPENSSL_NO_BUF_FREELISTS
 typedef struct ssl3_buf_freelist_st
 	{
 	size_t chunklen;
 	unsigned int len;
 	struct ssl3_buf_freelist_entry_st *head;
 	} SSL3_BUF_FREELIST;
 
 typedef struct ssl3_buf_freelist_entry_st
 	{
 	struct ssl3_buf_freelist_entry_st *next;
 	} SSL3_BUF_FREELIST_ENTRY;
 #endif
 
 extern SSL3_ENC_METHOD ssl3_undef_enc_method;
 OPENSSL_EXTERN const SSL_CIPHER ssl2_ciphers[];
 OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[];
 
 
 SSL_METHOD *ssl_bad_method(int ver);
 
 extern SSL3_ENC_METHOD TLSv1_enc_data;
 extern SSL3_ENC_METHOD SSLv3_enc_data;
 extern SSL3_ENC_METHOD DTLSv1_enc_data;
 
 #define SSL_IS_DTLS(s) (s->method->version == DTLS1_VERSION)
 
 #define IMPLEMENT_tls_meth_func(version, func_name, s_accept, s_connect, \
 				s_get_meth) \
 const SSL_METHOD *func_name(void)  \
 	{ \
 	static const SSL_METHOD func_name##_data= { \
 		version, \
 		tls1_new, \
 		tls1_clear, \
 		tls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		tls1_default_timeout, \
 		&TLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 const SSL_METHOD *func_name(void)  \
 	{ \
 	static const SSL_METHOD func_name##_data= { \
 		SSL3_VERSION, \
 		ssl3_new, \
 		ssl3_clear, \
 		ssl3_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		ssl3_default_timeout, \
 		&SSLv3_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 const SSL_METHOD *func_name(void)  \
 	{ \
 	static const SSL_METHOD func_name##_data= { \
 	TLS1_2_VERSION, \
 	tls1_new, \
 	tls1_clear, \
 	tls1_free, \
 	s_accept, \
 	s_connect, \
 	ssl23_read, \
 	ssl23_peek, \
 	ssl23_write, \
 	ssl_undefined_function, \
 	ssl_undefined_function, \
 	ssl_ok, \
 	ssl3_get_message, \
 	ssl3_read_bytes, \
 	ssl3_write_bytes, \
 	ssl3_dispatch_alert, \
 	ssl3_ctrl, \
 	ssl3_ctx_ctrl, \
 	ssl23_get_cipher_by_char, \
 	ssl23_put_cipher_by_char, \
 	ssl_undefined_const_function, \
 	ssl23_num_ciphers, \
 	ssl23_get_cipher, \
 	s_get_meth, \
 	ssl23_default_timeout, \
 	&ssl3_undef_enc_method, \
 	ssl_undefined_void_function, \
 	ssl3_callback_ctrl, \
 	ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl2_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 const SSL_METHOD *func_name(void)  \
 	{ \
 	static const SSL_METHOD func_name##_data= { \
 		SSL2_VERSION, \
 		ssl2_new,	/* local */ \
 		ssl2_clear,	/* local */ \
 		ssl2_free,	/* local */ \
 		s_accept, \
 		s_connect, \
 		ssl2_read, \
 		ssl2_peek, \
 		ssl2_write, \
 		ssl2_shutdown, \
 		ssl_ok,	/* NULL - renegotiate */ \
 		ssl_ok,	/* NULL - check renegotiate */ \
 		NULL, /* NULL - ssl_get_message */ \
 		NULL, /* NULL - ssl_get_record */ \
 		NULL, /* NULL - ssl_write_bytes */ \
 		NULL, /* NULL - dispatch_alert */ \
 		ssl2_ctrl,	/* local */ \
 		ssl2_ctx_ctrl,	/* local */ \
 		ssl2_get_cipher_by_char, \
 		ssl2_put_cipher_by_char, \
 		ssl2_pending, \
 		ssl2_num_ciphers, \
 		ssl2_get_cipher, \
 		s_get_meth, \
 		ssl2_default_timeout, \
 		&ssl3_undef_enc_method, \
 		ssl_undefined_void_function, \
 		ssl2_callback_ctrl,	/* local */ \
 		ssl2_ctx_callback_ctrl,	/* local */ \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 const SSL_METHOD *func_name(void)  \
 	{ \
 	static const SSL_METHOD func_name##_data= { \
 		DTLS1_VERSION, \
 		dtls1_new, \
 		dtls1_clear, \
 		dtls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		dtls1_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		dtls1_get_message, \
 		dtls1_read_bytes, \
 		dtls1_write_app_data_bytes, \
 		dtls1_dispatch_alert, \
 		dtls1_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		dtls1_get_cipher, \
 		s_get_meth, \
 		dtls1_default_timeout, \
 		&DTLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 struct openssl_ssl_test_functions
 	{
 	int (*p_ssl_init_wbio_buffer)(SSL *s, int push);
 	int (*p_ssl3_setup_buffers)(SSL *s);
 	int (*p_tls1_process_heartbeat)(SSL *s);
 	int (*p_dtls1_process_heartbeat)(SSL *s);
 	};
 
 #ifndef OPENSSL_UNIT_TEST
 
 void ssl_clear_cipher_ctx(SSL *s);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
 int ssl_cert_inst(CERT **o);
 void ssl_cert_free(CERT *c);
 SESS_CERT *ssl_sess_cert_new(void);
 void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
 				  ssl_cipher_id);
 int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
 			const SSL_CIPHER * const *bp);
 STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
 					       STACK_OF(SSL_CIPHER) **skp);
 int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                              int (*put_cb)(const SSL_CIPHER *, unsigned char *));
 STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
 					     STACK_OF(SSL_CIPHER) **pref,
 					     STACK_OF(SSL_CIPHER) **sorted,
 					     const char *rule_str);
 void ssl_update_cache(SSL *s, int mode);
 int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
 		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
 int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);			   
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);
 CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
 X509 *ssl_get_server_send_cert(const SSL *);
 EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
 int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
 void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
 STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
 int ssl_verify_alarm_type(long type);
 void ssl_load_ciphers(void);
 int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
 
 int ssl2_enc_init(SSL *s, int client);
 int ssl2_generate_key_material(SSL *s);
 int ssl2_enc(SSL *s,int send_data);
 void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
 const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
 int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 int ssl2_part_read(SSL *s, unsigned long f, int i);
 int ssl2_do_write(SSL *s);
 int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
 void ssl2_return_error(SSL *s,int reason);
 void ssl2_write_error(SSL *s);
 int ssl2_num_ciphers(void);
 const SSL_CIPHER *ssl2_get_cipher(unsigned int u);
 int	ssl2_new(SSL *s);
 void	ssl2_free(SSL *s);
 int	ssl2_accept(SSL *s);
 int	ssl2_connect(SSL *s);
 int	ssl2_read(SSL *s, void *buf, int len);
 int	ssl2_peek(SSL *s, void *buf, int len);
 int	ssl2_write(SSL *s, const void *buf, int len);
 int	ssl2_shutdown(SSL *s);
 void	ssl2_clear(SSL *s);
 long	ssl2_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl2_pending(const SSL *s);
 long	ssl2_default_timeout(void );
 
 const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
 int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 void ssl3_init_finished_mac(SSL *s);
 int ssl3_send_server_certificate(SSL *s);
 int ssl3_send_newsession_ticket(SSL *s);
 int ssl3_send_cert_status(SSL *s);
 int ssl3_get_finished(SSL *s,int state_a,int state_b);
 int ssl3_setup_key_block(SSL *s);
 int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
 int ssl3_change_cipher_state(SSL *s,int which);
 void ssl3_cleanup_key_block(SSL *s);
 int ssl3_do_write(SSL *s,int type);
 int ssl3_send_alert(SSL *s,int level, int desc);
 int ssl3_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int ssl3_get_req_cert_type(SSL *s,unsigned char *p);
 long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen);
 int ssl3_num_ciphers(void);
 const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
 int ssl3_renegotiate(SSL *ssl); 
 int ssl3_renegotiate_check(SSL *ssl); 
 int ssl3_dispatch_alert(SSL *s);
 int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
 int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,unsigned char *p);
 int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
 void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
 int ssl3_enc(SSL *s, int send_data);
 int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
 void ssl3_free_digest_list(SSL *s);
 unsigned long ssl3_output_cert_chain(SSL *s, X509 *x);
 SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt,
 			       STACK_OF(SSL_CIPHER) *srvr);
 int	ssl3_setup_buffers(SSL *s);
 int	ssl3_setup_read_buffer(SSL *s);
 int	ssl3_setup_write_buffer(SSL *s);
 int	ssl3_release_read_buffer(SSL *s);
 int	ssl3_release_write_buffer(SSL *s);
 int	ssl3_digest_cached_records(SSL *s);
 int	ssl3_new(SSL *s);
 void	ssl3_free(SSL *s);
 int	ssl3_accept(SSL *s);
 int	ssl3_connect(SSL *s);
 int	ssl3_read(SSL *s, void *buf, int len);
 int	ssl3_peek(SSL *s, void *buf, int len);
 int	ssl3_write(SSL *s, const void *buf, int len);
 int	ssl3_shutdown(SSL *s);
 void	ssl3_clear(SSL *s);
 long	ssl3_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl3_pending(const SSL *s);
 
 void ssl3_record_sequence_update(unsigned char *seq);
 int ssl3_do_change_cipher_spec(SSL *ssl);
 long ssl3_default_timeout(void );
 
 int ssl23_num_ciphers(void );
 const SSL_CIPHER *ssl23_get_cipher(unsigned int u);
 int ssl23_read(SSL *s, void *buf, int len);
 int ssl23_peek(SSL *s, void *buf, int len);
 int ssl23_write(SSL *s, const void *buf, int len);
 int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
 const SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p);
 long ssl23_default_timeout(void );
 
 long tls1_default_timeout(void);
 int dtls1_do_write(SSL *s,int type);
 int ssl3_read_n(SSL *s, int n, int max, int extend);
 int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_do_compress(SSL *ssl);
 int ssl3_do_uncompress(SSL *ssl);
 int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
 	unsigned int len);
 unsigned char *dtls1_set_message_header(SSL *s, 
 	unsigned char *p, unsigned char mt,	unsigned long len, 
 	unsigned long frag_off, unsigned long frag_len);
 
 int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
 int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
 
 int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
 int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
 unsigned long dtls1_output_cert_chain(SSL *s, X509 *x);
 int dtls1_read_failed(SSL *s, int code);
 int dtls1_buffer_message(SSL *s, int ccs);
 int dtls1_retransmit_message(SSL *s, unsigned short seq, 
 	unsigned long frag_off, int *found);
 int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
 int dtls1_retransmit_buffered_messages(SSL *s);
 void dtls1_clear_record_buffer(SSL *s);
 void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
 void dtls1_reset_seq_numbers(SSL *s, int rw);
 long dtls1_default_timeout(void);
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
 int dtls1_check_timeout_num(SSL *s);
 int dtls1_handle_timeout(SSL *s);
 const SSL_CIPHER *dtls1_get_cipher(unsigned int u);
 void dtls1_start_timer(SSL *s);
 void dtls1_stop_timer(SSL *s);
 int dtls1_is_timer_expired(SSL *s);
 void dtls1_double_timeout(SSL *s);
 int dtls1_send_newsession_ticket(SSL *s);
 unsigned int dtls1_min_mtu(SSL *s);
 unsigned int dtls1_link_min_mtu(void);
 void dtls1_hm_fragment_free(hm_fragment *frag);
 
 /* some client-only functions */
 int ssl3_client_hello(SSL *s);
 int ssl3_get_server_hello(SSL *s);
 int ssl3_get_certificate_request(SSL *s);
 int ssl3_get_new_session_ticket(SSL *s);
 int ssl3_get_cert_status(SSL *s);
 int ssl3_get_server_done(SSL *s);
 int ssl3_send_client_verify(SSL *s);
 int ssl3_send_client_certificate(SSL *s);
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
 int ssl3_send_client_key_exchange(SSL *s);
 int ssl3_get_key_exchange(SSL *s);
 int ssl3_get_server_certificate(SSL *s);
 int ssl3_check_cert_and_algorithm(SSL *s);
 #ifndef OPENSSL_NO_TLSEXT
 # ifndef OPENSSL_NO_NEXTPROTONEG
 int ssl3_send_next_proto(SSL *s);
 # endif
 #endif
 
 int dtls1_client_hello(SSL *s);
 int dtls1_send_client_certificate(SSL *s);
 int dtls1_send_client_key_exchange(SSL *s);
 int dtls1_send_client_verify(SSL *s);
 
 /* some server-only functions */
 int ssl3_get_client_hello(SSL *s);
 int ssl3_send_server_hello(SSL *s);
 int ssl3_send_hello_request(SSL *s);
 int ssl3_send_server_key_exchange(SSL *s);
 int ssl3_send_certificate_request(SSL *s);
 int ssl3_send_server_done(SSL *s);
 int ssl3_check_client_hello(SSL *s);
 int ssl3_get_client_certificate(SSL *s);
 int ssl3_get_client_key_exchange(SSL *s);
 int ssl3_get_cert_verify(SSL *s);
 #ifndef OPENSSL_NO_NEXTPROTONEG
 int ssl3_get_next_proto(SSL *s);
 #endif
 
 int dtls1_send_hello_request(SSL *s);
 int dtls1_send_server_hello(SSL *s);
 int dtls1_send_server_certificate(SSL *s);
 int dtls1_send_server_key_exchange(SSL *s);
 int dtls1_send_certificate_request(SSL *s);
 int dtls1_send_server_done(SSL *s);
 
 
 
 int ssl23_accept(SSL *s);
 int ssl23_connect(SSL *s);
 int ssl23_read_bytes(SSL *s, int n);
 int ssl23_write_bytes(SSL *s);
 
 int tls1_new(SSL *s);
 void tls1_free(SSL *s);
 void tls1_clear(SSL *s);
 long tls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 
 int dtls1_new(SSL *s);
 int	dtls1_accept(SSL *s);
 int	dtls1_connect(SSL *s);
 void dtls1_free(SSL *s);
 void dtls1_clear(SSL *s);
 long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 int dtls1_shutdown(SSL *s);
 
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int dtls1_get_record(SSL *s);
 int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
 	unsigned int len, int create_empty_fragement);
 int dtls1_dispatch_alert(SSL *s);
 int dtls1_enc(SSL *s, int snd);
 
 int ssl_init_wbio_buffer(SSL *s, int push);
 void ssl_free_wbio_buffer(SSL *s);
 
 int tls1_change_cipher_state(SSL *s, int which);
 int tls1_setup_key_block(SSL *s);
 int tls1_enc(SSL *s, int snd);
 int tls1_final_finish_mac(SSL *s,
 	const char *str, int slen, unsigned char *p);
 int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
 int tls1_mac(SSL *ssl, unsigned char *md, int snd);
 int tls1_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
 	const char *label, size_t llen,
 	const unsigned char *p, size_t plen, int use_context);
 int tls1_alert_code(int code);
 int ssl3_alert_code(int code);
 int ssl_ok(SSL *s);
 
 #ifndef OPENSSL_NO_ECDH
 int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
 #endif
 
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
 
 #ifndef OPENSSL_NO_EC
 int tls1_ec_curve_id2nid(int curve_id);
 int tls1_ec_nid2curve_id(int nid);
 #endif /* OPENSSL_NO_EC */
 
 #ifndef OPENSSL_NO_TLSEXT
 unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit); 
 unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit); 
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_prepare_clienthello_tlsext(SSL *s);
 int ssl_prepare_serverhello_tlsext(SSL *s);
 int ssl_check_clienthello_tlsext_early(SSL *s);
 int ssl_check_clienthello_tlsext_late(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
 
 #ifndef OPENSSL_NO_HEARTBEATS
 int tls1_heartbeat(SSL *s);
 int dtls1_heartbeat(SSL *s);
 int tls1_process_heartbeat(SSL *s);
 int dtls1_process_heartbeat(SSL *s);
 #endif
 
 #ifdef OPENSSL_NO_SHA256
 #define tlsext_tick_md	EVP_sha1
 #else
 #define tlsext_tick_md	EVP_sha256
 #endif
 int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 				const unsigned char *limit, SSL_SESSION **ret);
 
 int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
 				const EVP_MD *md);
 int tls12_get_sigid(const EVP_PKEY *pk);
 const EVP_MD *tls12_get_hash(unsigned char hash_alg);
 
 #endif
 EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 long ssl_get_algorithm2(SSL *s);
 int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
 int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
 
 int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
 int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al);
 int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
 int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al);
 
 /* s3_cbc.c */
 void ssl3_cbc_copy_mac(unsigned char* out,
 		       const SSL3_RECORD *rec,
 		       unsigned md_size,unsigned orig_len);
 int ssl3_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 int tls1_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
 void ssl3_cbc_digest_record(
 	const EVP_MD_CTX *ctx,
 	unsigned char* md_out,
 	size_t* md_out_size,
 	const unsigned char header[13],
 	const unsigned char *data,
 	size_t data_plus_mac_size,
 	size_t data_plus_mac_plus_padding_size,
 	const unsigned char *mac_secret,
 	unsigned mac_secret_length,
 	char is_sslv3);
 
 void tls_fips_digest_extra(
 	const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx,
 	const unsigned char *data, size_t data_len, size_t orig_len);
 
 int srp_verify_server_param(SSL *s, int *al);
 
 #else
 
 #define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer
 #define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers
 #define tls1_process_heartbeat SSL_test_functions()->p_tls1_process_heartbeat
 #define dtls1_process_heartbeat SSL_test_functions()->p_dtls1_process_heartbeat
 
 #endif
 #endif
Index: releng/10.1/crypto/openssl/ssl/ssl_sess.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/ssl_sess.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/ssl_sess.c	(revision 284295)
@@ -1,1173 +1,1297 @@
 /* ssl/ssl_sess.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2005 Nokia. All rights reserved.
  *
  * The portions of the attached software ("Contribution") is developed by
  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
  * license.
  *
  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
  * support (see RFC 4279) to OpenSSL.
  *
  * No patent licenses or other rights except those expressly stated in
  * the OpenSSL open source license shall be deemed granted or received
  * expressly, by implication, estoppel, or otherwise.
  *
  * No assurances are provided by Nokia that the Contribution does not
  * infringe the patent or other intellectual property rights of any third
  * party or that the license provides you with all the necessary rights
  * to make use of the Contribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include "ssl_locl.h"
 
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
 
 SSL_SESSION *SSL_get_session(const SSL *ssl)
 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
 	{
 	return(ssl->session);
 	}
 
 SSL_SESSION *SSL_get1_session(SSL *ssl)
 /* variant of SSL_get_session: caller really gets something */
 	{
 	SSL_SESSION *sess;
 	/* Need to lock this all up rather than just use CRYPTO_add so that
 	 * somebody doesn't free ssl->session between when we check it's
 	 * non-null and when we up the reference count. */
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
 	sess = ssl->session;
 	if(sess)
 		sess->references++;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
 	return(sess);
 	}
 
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
 	{
 	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
 	}
 
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
 	{
 	return(CRYPTO_get_ex_data(&s->ex_data,idx));
 	}
 
 SSL_SESSION *SSL_SESSION_new(void)
 	{
 	SSL_SESSION *ss;
 
 	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
 	if (ss == NULL)
 		{
 		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	memset(ss,0,sizeof(SSL_SESSION));
 
 	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
 	ss->references=1;
 	ss->timeout=60*5+4; /* 5 minute timeout by default */
 	ss->time=(unsigned long)time(NULL);
 	ss->prev=NULL;
 	ss->next=NULL;
 	ss->compress_meth=0;
 #ifndef OPENSSL_NO_TLSEXT
 	ss->tlsext_hostname = NULL; 
 #ifndef OPENSSL_NO_EC
 	ss->tlsext_ecpointformatlist_length = 0;
 	ss->tlsext_ecpointformatlist = NULL;
 	ss->tlsext_ellipticcurvelist_length = 0;
 	ss->tlsext_ellipticcurvelist = NULL;
 #endif
 #endif
 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 #ifndef OPENSSL_NO_PSK
 	ss->psk_identity_hint=NULL;
 	ss->psk_identity=NULL;
 #endif
 #ifndef OPENSSL_NO_SRP
 	ss->srp_username=NULL;
 #endif
 	return(ss);
 	}
 
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+    /*
+     * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+# ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->tlsext_ellipticcurvelist_length);
+        if (dest->tlsext_ellipticcurvelist == NULL)
+            goto err;
+    }
+# endif
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+#ifndef OPENSSL_NO_SRP
+    if (src->srp_username) {
+        dest->srp_username = BUF_strdup(src->srp_username);
+        if (dest->srp_username == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)
 		*len = s->session_id_length;
 	return s->session_id;
 	}
 
 unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
 	{
 	return s->compress_meth;
 	}
 
 /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
  * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
  * until we have no conflict is going to complete in one iteration pretty much
  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  * and we still can't avoid a conflict - well that's a reasonable point to call
  * it quits. Either the RAND code is broken or someone is trying to open roughly
  * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
  * store that many sessions is perhaps a more interesting question ... */
 
 #define MAX_SESS_ID_ATTEMPTS 10
 static int def_generate_session_id(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len)
 {
 	unsigned int retry = 0;
 	do
 		if (RAND_pseudo_bytes(id, *id_len) <= 0)
 			return 0;
 	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
 		(++retry < MAX_SESS_ID_ATTEMPTS));
 	if(retry < MAX_SESS_ID_ATTEMPTS)
 		return 1;
 	/* else - woops a session_id match */
 	/* XXX We should also check the external cache --
 	 * but the probability of a collision is negligible, and
 	 * we could not prevent the concurrent creation of sessions
 	 * with identical IDs since we currently don't have means
 	 * to atomically check whether a session ID already exists
 	 * and make a reservation for it if it does not
 	 * (this problem applies to the internal cache as well).
 	 */
 	return 0;
 }
 
 int ssl_get_new_session(SSL *s, int session)
 	{
 	/* This gets used by clients and servers. */
 
 	unsigned int tmp;
 	SSL_SESSION *ss=NULL;
 	GEN_SESSION_CB cb = def_generate_session_id;
 
 	if ((ss=SSL_SESSION_new()) == NULL) return(0);
 
 	/* If the context has a default timeout, use it */
 	if (s->session_ctx->session_timeout == 0)
 		ss->timeout=SSL_get_default_timeout(s);
 	else
 		ss->timeout=s->session_ctx->session_timeout;
 
 	if (s->session != NULL)
 		{
 		SSL_SESSION_free(s->session);
 		s->session=NULL;
 		}
 
 	if (session)
 		{
 		if (s->version == SSL2_VERSION)
 			{
 			ss->ssl_version=SSL2_VERSION;
 			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == SSL3_VERSION)
 			{
 			ss->ssl_version=SSL3_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == TLS1_VERSION)
 			{
 			ss->ssl_version=TLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == TLS1_1_VERSION)
 			{
 			ss->ssl_version=TLS1_1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == TLS1_2_VERSION)
 			{
 			ss->ssl_version=TLS1_2_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_BAD_VER)
 			{
 			ss->ssl_version=DTLS1_BAD_VER;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_VERSION)
 			{
 			ss->ssl_version=DTLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		/*
 		 * If RFC5077 ticket, use empty session ID (as server).
 		 * Note that:
 		 * (a) ssl_get_prev_session() does lookahead into the
 		 *     ClientHello extensions to find the session ticket.
 		 *     When ssl_get_prev_session() fails, s3_srvr.c calls
 		 *     ssl_get_new_session() in ssl3_get_client_hello().
 		 *     At that point, it has not yet parsed the extensions,
 		 *     however, because of the lookahead, it already knows
 		 *     whether a ticket is expected or not.
 		 *
 		 * (b) s3_clnt.c calls ssl_get_new_session() before parsing
 		 *     ServerHello extensions, and before recording the session
 		 *     ID received from the server, so this block is a noop.
 		 */
 		if (s->tlsext_ticket_expected)
 			{
 			ss->session_id_length = 0;
 			goto sess_id_done;
 			}
 #endif
 		/* Choose which callback will set the session ID */
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		if(s->generate_session_id)
 			cb = s->generate_session_id;
 		else if(s->session_ctx->generate_session_id)
 			cb = s->session_ctx->generate_session_id;
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		/* Choose a session ID */
 		tmp = ss->session_id_length;
 		if(!cb(s, ss->session_id, &tmp))
 			{
 			/* The callback failed */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* Don't allow the callback to set the session length to zero.
 		 * nor set it higher than it was. */
 		if(!tmp || (tmp > ss->session_id_length))
 			{
 			/* The callback set an illegal length */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* If the session length was shrunk and we're SSLv2, pad it */
 		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
 			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
 		else
 			ss->session_id_length = tmp;
 		/* Finally, check for a conflict */
 		if(SSL_has_matching_session_id(s, ss->session_id,
 						ss->session_id_length))
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CONFLICT);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		sess_id_done:
 		if (s->tlsext_hostname) {
 			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
 			if (ss->tlsext_hostname == NULL) {
 				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 				SSL_SESSION_free(ss);
 				return 0;
 				}
 			}
 #ifndef OPENSSL_NO_EC
 		if (s->tlsext_ecpointformatlist)
 			{
 			if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
 			if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
 				{
 				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
 				SSL_SESSION_free(ss);
 				return 0;
 				}
 			ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
 			memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
 			}
 		if (s->tlsext_ellipticcurvelist)
 			{
 			if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
 			if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
 				{
 				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
 				SSL_SESSION_free(ss);
 				return 0;
 				}
 			ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length;
 			memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
 			}
 #endif
 #endif
 		}
 	else
 		{
 		ss->session_id_length=0;
 		}
 
 	if (s->sid_ctx_length > sizeof ss->sid_ctx)
 		{
 		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 		SSL_SESSION_free(ss);
 		return 0;
 		}
 	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
 	ss->sid_ctx_length=s->sid_ctx_length;
 	s->session=ss;
 	ss->ssl_version=s->version;
 	ss->verify_result = X509_V_OK;
 
 	return(1);
 	}
 
 /* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
  * connection. It is only called by servers.
  *
  *   session_id: points at the session ID in the ClientHello. This code will
  *       read past the end of this in order to parse out the session ticket
  *       extension, if any.
  *   len: the length of the session ID.
  *   limit: a pointer to the first byte after the ClientHello.
  *
  * Returns:
  *   -1: error
  *    0: a session may have been found.
  *
  * Side effects:
  *   - If a session is found then s->session is pointed at it (after freeing an
  *     existing session if need be) and s->verify_result is set from the session.
  *   - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
  *     if the server should issue a new session ticket (to 0 otherwise).
  */
 int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
 			const unsigned char *limit)
 	{
 	/* This is used only by servers. */
 
 	SSL_SESSION *ret=NULL;
 	int fatal = 0;
 	int try_session_cache = 1;
 #ifndef OPENSSL_NO_TLSEXT
 	int r;
 #endif
 
 	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
 		goto err;
 
 	if (len == 0)
 		try_session_cache = 0;
 
 #ifndef OPENSSL_NO_TLSEXT
 	r = tls1_process_ticket(s, session_id, len, limit, &ret); /* sets s->tlsext_ticket_expected */
 	switch (r)
 		{
 	case -1: /* Error during processing */
 		fatal = 1;
 		goto err;
 	case 0: /* No ticket found */
 	case 1: /* Zero length ticket found */
 		break; /* Ok to carry on processing session id. */
 	case 2: /* Ticket found but not decrypted. */
 	case 3: /* Ticket decrypted, *ret has been set. */
 		try_session_cache = 0;
 		break;
 	default:
 		abort();
 		}
 #endif
 
 	if (try_session_cache &&
 	    ret == NULL &&
 	    !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 		{
 		SSL_SESSION data;
 		data.ssl_version=s->version;
 		data.session_id_length=len;
 		if (len == 0)
 			return 0;
 		memcpy(data.session_id,session_id,len);
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data);
 		if (ret != NULL)
 			{
 			/* don't allow other threads to steal it: */
 			CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 			}
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		if (ret == NULL)
 			s->session_ctx->stats.sess_miss++;
 		}
 
 	if (try_session_cache &&
 	    ret == NULL &&
 	    s->session_ctx->get_session_cb != NULL)
 		{
 		int copy=1;
 	
 		if ((ret=s->session_ctx->get_session_cb(s,session_id,len,©)))
 			{
 			s->session_ctx->stats.sess_cb_hit++;
 
 			/* Increment reference count now if the session callback
 			 * asks us to do so (note that if the session structures
 			 * returned by the callback are shared between threads,
 			 * it must handle the reference count itself [i.e. copy == 0],
 			 * or things won't be thread-safe). */
 			if (copy)
 				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 
 			/* Add the externally cached session to the internal
 			 * cache as well if and only if we are supposed to. */
 			if(!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
 				/* The following should not return 1, otherwise,
 				 * things are very strange */
 				SSL_CTX_add_session(s->session_ctx,ret);
 			}
 		}
 
 	if (ret == NULL)
 		goto err;
 
 	/* Now ret is non-NULL and we own one of its reference counts. */
 
 	if (ret->sid_ctx_length != s->sid_ctx_length
 	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
 		{
 		/* We have the session requested by the client, but we don't
 		 * want to use it in this context. */
 		goto err; /* treat like cache miss */
 		}
 	
 	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
 		{
 		/* We can't be sure if this session is being used out of
 		 * context, which is especially important for SSL_VERIFY_PEER.
 		 * The application should have used SSL[_CTX]_set_session_id_context.
 		 *
 		 * For this error case, we generate an error instead of treating
 		 * the event like a cache miss (otherwise it would be easy for
 		 * applications to effectively disable the session cache by
 		 * accident without anyone noticing).
 		 */
 		
 		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
 		fatal = 1;
 		goto err;
 		}
 
 	if (ret->cipher == NULL)
 		{
 		unsigned char buf[5],*p;
 		unsigned long l;
 
 		p=buf;
 		l=ret->cipher_id;
 		l2n(l,p);
 		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR)
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
 		else 
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
 		if (ret->cipher == NULL)
 			goto err;
 		}
 
 	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
 		{
 		s->session_ctx->stats.sess_timeout++;
 		if (try_session_cache)
 			{
 			/* session was from the cache, so remove it */
 			SSL_CTX_remove_session(s->session_ctx,ret);
 			}
 		goto err;
 		}
 
 	s->session_ctx->stats.sess_hit++;
 
 	if (s->session != NULL)
 		SSL_SESSION_free(s->session);
 	s->session=ret;
 	s->verify_result = s->session->verify_result;
 	return 1;
 
  err:
 	if (ret != NULL)
 		{
 		SSL_SESSION_free(ret);
 #ifndef OPENSSL_NO_TLSEXT
 		if (!try_session_cache)
 			{
 			/* The session was from a ticket, so we should
 			 * issue a ticket for the new session */
 			s->tlsext_ticket_expected = 1;
 			}
 #endif
 		}
 	if (fatal)
 		return -1;
 	else
 		return 0;
 	}
 
 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
 	{
 	int ret=0;
 	SSL_SESSION *s;
 
 	/* add just 1 reference count for the SSL_CTX's session cache
 	 * even though it has two ways of access: each session is in a
 	 * doubly linked list and an lhash */
 	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
 	/* if session c is in already in cache, we take back the increment later */
 
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	s=lh_SSL_SESSION_insert(ctx->sessions,c);
 	
 	/* s != NULL iff we already had a session with the given PID.
 	 * In this case, s == c should hold (then we did not really modify
 	 * ctx->sessions), or we're in trouble. */
 	if (s != NULL && s != c)
 		{
 		/* We *are* in trouble ... */
 		SSL_SESSION_list_remove(ctx,s);
 		SSL_SESSION_free(s);
 		/* ... so pretend the other session did not exist in cache
 		 * (we cannot handle two SSL_SESSION structures with identical
 		 * session ID in the same cache, which could happen e.g. when
 		 * two threads concurrently obtain the same session from an external
 		 * cache) */
 		s = NULL;
 		}
 
  	/* Put at the head of the queue unless it is already in the cache */
 	if (s == NULL)
 		SSL_SESSION_list_add(ctx,c);
 
 	if (s != NULL)
 		{
 		/* existing cache entry -- decrement previously incremented reference
 		 * count because it already takes into account the cache */
 
 		SSL_SESSION_free(s); /* s == c */
 		ret=0;
 		}
 	else
 		{
 		/* new cache entry -- remove old ones if cache has become too large */
 		
 		ret=1;
 
 		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
 			{
 			while (SSL_CTX_sess_number(ctx) >
 				SSL_CTX_sess_get_cache_size(ctx))
 				{
 				if (!remove_session_lock(ctx,
 					ctx->session_cache_tail, 0))
 					break;
 				else
 					ctx->stats.sess_cache_full++;
 				}
 			}
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	return(ret);
 	}
 
 int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
 {
 	return remove_session_lock(ctx, c, 1);
 }
 
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
 	{
 	SSL_SESSION *r;
 	int ret=0;
 
 	if ((c != NULL) && (c->session_id_length != 0))
 		{
 		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 		if ((r = lh_SSL_SESSION_retrieve(ctx->sessions,c)) == c)
 			{
 			ret=1;
 			r=lh_SSL_SESSION_delete(ctx->sessions,c);
 			SSL_SESSION_list_remove(ctx,c);
 			}
 
 		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 
 		if (ret)
 			{
 			r->not_resumable=1;
 			if (ctx->remove_session_cb != NULL)
 				ctx->remove_session_cb(ctx,r);
 			SSL_SESSION_free(r);
 			}
 		}
 	else
 		ret=0;
 	return(ret);
 	}
 
 void SSL_SESSION_free(SSL_SESSION *ss)
 	{
 	int i;
 
 	if(ss == NULL)
 	    return;
 
 	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
 #ifdef REF_PRINT
 	REF_PRINT("SSL_SESSION",ss);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
 		abort(); /* ok */
 		}
 #endif
 
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
 	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
 	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key);
 	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id);
 	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
 	if (ss->peer != NULL) X509_free(ss->peer);
 	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
 #ifndef OPENSSL_NO_TLSEXT
 	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
 	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
 #ifndef OPENSSL_NO_EC
 	ss->tlsext_ecpointformatlist_length = 0;
 	if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
 	ss->tlsext_ellipticcurvelist_length = 0;
 	if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
 #endif /* OPENSSL_NO_EC */
 #endif
 #ifndef OPENSSL_NO_PSK
 	if (ss->psk_identity_hint != NULL)
 		OPENSSL_free(ss->psk_identity_hint);
 	if (ss->psk_identity != NULL)
 		OPENSSL_free(ss->psk_identity);
 #endif
 #ifndef OPENSSL_NO_SRP
 	if (ss->srp_username != NULL)
 		OPENSSL_free(ss->srp_username);
 #endif
 	OPENSSL_cleanse(ss,sizeof(*ss));
 	OPENSSL_free(ss);
 	}
 
 int SSL_set_session(SSL *s, SSL_SESSION *session)
 	{
 	int ret=0;
 	const SSL_METHOD *meth;
 
 	if (session != NULL)
 		{
 		meth=s->ctx->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			meth=s->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			{
 			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
 			return(0);
 			}
 
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			}
 
 #ifndef OPENSSL_NO_KRB5
                 if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
                     session->krb5_client_princ_len > 0)
                 {
                     s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
                     memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
                             session->krb5_client_princ_len);
                     s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
                 }
 #endif /* OPENSSL_NO_KRB5 */
 
 		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
 		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
 		if (s->session != NULL)
 			SSL_SESSION_free(s->session);
 		s->session=session;
 		s->verify_result = s->session->verify_result;
 		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
 		ret=1;
 		}
 	else
 		{
 		if (s->session != NULL)
 			{
 			SSL_SESSION_free(s->session);
 			s->session=NULL;
 			}
 
 		meth=s->ctx->method;
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			}
 		ret=1;
 		}
 	return(ret);
 	}
 
 long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->timeout=t;
 	return(1);
 	}
 
 long SSL_SESSION_get_timeout(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->timeout);
 	}
 
 long SSL_SESSION_get_time(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->time);
 	}
 
 long SSL_SESSION_set_time(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->time=t;
 	return(t);
 	}
 
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
 	{
 	return s->peer;
 	}
 
 int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
 			       unsigned int sid_ctx_len)
 	{
 	if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)
 		{
 		SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
 		return 0;
 		}
 	s->sid_ctx_length=sid_ctx_len;
 	memcpy(s->sid_ctx,sid_ctx,sid_ctx_len);
 
 	return 1;
 	}
 
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
 	{
 	long l;
 	if (s == NULL) return(0);
 	l=s->session_timeout;
 	s->session_timeout=t;
 	return(l);
 	}
 
 long SSL_CTX_get_timeout(const SSL_CTX *s)
 	{
 	if (s == NULL) return(0);
 	return(s->session_timeout);
 	}
 
 #ifndef OPENSSL_NO_TLSEXT
 int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
 	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
 	{
 	if (s == NULL) return(0);
 	s->tls_session_secret_cb = tls_session_secret_cb;
 	s->tls_session_secret_cb_arg = arg;
 	return(1);
 	}
 
 int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
 				  void *arg)
 	{
 	if (s == NULL) return(0);
 	s->tls_session_ticket_ext_cb = cb;
 	s->tls_session_ticket_ext_cb_arg = arg;
 	return(1);
 	}
 
 int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
 	{
 	if (s->version >= TLS1_VERSION)
 		{
 		if (s->tlsext_session_ticket)
 			{
 			OPENSSL_free(s->tlsext_session_ticket);
 			s->tlsext_session_ticket = NULL;
 			}
 
 		s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
 		if (!s->tlsext_session_ticket)
 			{
 			SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 
 		if (ext_data)
 			{
 			s->tlsext_session_ticket->length = ext_len;
 			s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
 			memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
 			}
 		else
 			{
 			s->tlsext_session_ticket->length = 0;
 			s->tlsext_session_ticket->data = NULL;
 			}
 
 		return 1;
 		}
 
 	return 0;
 	}
 #endif /* OPENSSL_NO_TLSEXT */
 
 typedef struct timeout_param_st
 	{
 	SSL_CTX *ctx;
 	long time;
 	LHASH_OF(SSL_SESSION) *cache;
 	} TIMEOUT_PARAM;
 
 static void timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p)
 	{
 	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
 		{
 		/* The reason we don't call SSL_CTX_remove_session() is to
 		 * save on locking overhead */
 		(void)lh_SSL_SESSION_delete(p->cache,s);
 		SSL_SESSION_list_remove(p->ctx,s);
 		s->not_resumable=1;
 		if (p->ctx->remove_session_cb != NULL)
 			p->ctx->remove_session_cb(p->ctx,s);
 		SSL_SESSION_free(s);
 		}
 	}
 
 static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION, TIMEOUT_PARAM)
 
 void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
 	{
 	unsigned long i;
 	TIMEOUT_PARAM tp;
 
 	tp.ctx=s;
 	tp.cache=s->sessions;
 	if (tp.cache == NULL) return;
 	tp.time=t;
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	i=CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load;
 	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=0;
 	lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout),
 				 TIMEOUT_PARAM, &tp);
 	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=i;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	}
 
 int ssl_clear_bad_session(SSL *s)
 	{
 	if (	(s->session != NULL) &&
 		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
 		!(SSL_in_init(s) || SSL_in_before(s)))
 		{
 		SSL_CTX_remove_session(s->ctx,s->session);
 		return(1);
 		}
 	else
 		return(0);
 	}
 
 /* locked by SSL_CTX in the calling function */
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next == NULL) || (s->prev == NULL)) return;
 
 	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
 		{ /* last element in list */
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* only one element in list */
 			ctx->session_cache_head=NULL;
 			ctx->session_cache_tail=NULL;
 			}
 		else
 			{
 			ctx->session_cache_tail=s->prev;
 			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 			}
 		}
 	else
 		{
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* first element in list */
 			ctx->session_cache_head=s->next;
 			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 			}
 		else
 			{ /* middle of list */
 			s->next->prev=s->prev;
 			s->prev->next=s->next;
 			}
 		}
 	s->prev=s->next=NULL;
 	}
 
 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next != NULL) && (s->prev != NULL))
 		SSL_SESSION_list_remove(ctx,s);
 
 	if (ctx->session_cache_head == NULL)
 		{
 		ctx->session_cache_head=s;
 		ctx->session_cache_tail=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 		}
 	else
 		{
 		s->next=ctx->session_cache_head;
 		s->next->prev=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		ctx->session_cache_head=s;
 		}
 	}
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
 	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
 	{
 	ctx->new_session_cb=cb;
 	}
 
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
 	{
 	return ctx->new_session_cb;
 	}
 
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
 	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
 	{
 	ctx->remove_session_cb=cb;
 	}
 
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
 	{
 	return ctx->remove_session_cb;
 	}
 
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
 	SSL_SESSION *(*cb)(struct ssl_st *ssl,
 	         unsigned char *data,int len,int *copy))
 	{
 	ctx->get_session_cb=cb;
 	}
 
 SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
 	         unsigned char *data,int len,int *copy)
 	{
 	return ctx->get_session_cb;
 	}
 
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, 
 	void (*cb)(const SSL *ssl,int type,int val))
 	{
 	ctx->info_callback=cb;
 	}
 
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
 	{
 	return ctx->info_callback;
 	}
 
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
 	{
 	ctx->client_cert_cb=cb;
 	}
 
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
 	{
 	return ctx->client_cert_cb;
 	}
 
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
 	{
 	if (!ENGINE_init(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
 		return 0;
 		}
 	if(!ENGINE_get_ssl_client_cert_function(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
 		ENGINE_finish(e);
 		return 0;
 		}
 	ctx->client_cert_engine = e;
 	return 1;
 	}
 #endif
 
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
 	{
 	ctx->app_gen_cookie_cb=cb;
 	}
 
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
 	{
 	ctx->app_verify_cookie_cb=cb;
 	}
 
 IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
Index: releng/10.1/crypto/openssl/ssl/t1_lib.c
===================================================================
--- releng/10.1/crypto/openssl/ssl/t1_lib.c	(revision 284294)
+++ releng/10.1/crypto/openssl/ssl/t1_lib.c	(revision 284295)
@@ -1,2759 +1,2704 @@
 /* ssl/t1_lib.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include "ssl_locl.h"
 
 const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
 
 #ifndef OPENSSL_NO_TLSEXT
 static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
 				const unsigned char *sess_id, int sesslen,
 				SSL_SESSION **psess);
 #endif
 
 SSL3_ENC_METHOD TLSv1_enc_data={
 	tls1_enc,
 	tls1_mac,
 	tls1_setup_key_block,
 	tls1_generate_master_secret,
 	tls1_change_cipher_state,
 	tls1_final_finish_mac,
 	TLS1_FINISH_MAC_LENGTH,
 	tls1_cert_verify_mac,
 	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
 	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
 	tls1_alert_code,
 	tls1_export_keying_material,
 	};
 
 long tls1_default_timeout(void)
 	{
 	/* 2 hours, the 24 hours mentioned in the TLSv1 spec
 	 * is way too long for http, the cache would over fill */
 	return(60*60*2);
 	}
 
 int tls1_new(SSL *s)
 	{
 	if (!ssl3_new(s)) return(0);
 	s->method->ssl_clear(s);
 	return(1);
 	}
 
 void tls1_free(SSL *s)
 	{
 #ifndef OPENSSL_NO_TLSEXT
 	if (s->tlsext_session_ticket)
 		{
 		OPENSSL_free(s->tlsext_session_ticket);
 		}
 #endif /* OPENSSL_NO_TLSEXT */
 	ssl3_free(s);
 	}
 
 void tls1_clear(SSL *s)
 	{
 	ssl3_clear(s);
 	s->version = s->method->version;
 	}
 
 #ifndef OPENSSL_NO_EC
 
 static int nid_list[] =
 	{
 		NID_sect163k1, /* sect163k1 (1) */
 		NID_sect163r1, /* sect163r1 (2) */
 		NID_sect163r2, /* sect163r2 (3) */
 		NID_sect193r1, /* sect193r1 (4) */ 
 		NID_sect193r2, /* sect193r2 (5) */ 
 		NID_sect233k1, /* sect233k1 (6) */
 		NID_sect233r1, /* sect233r1 (7) */ 
 		NID_sect239k1, /* sect239k1 (8) */ 
 		NID_sect283k1, /* sect283k1 (9) */
 		NID_sect283r1, /* sect283r1 (10) */ 
 		NID_sect409k1, /* sect409k1 (11) */ 
 		NID_sect409r1, /* sect409r1 (12) */
 		NID_sect571k1, /* sect571k1 (13) */ 
 		NID_sect571r1, /* sect571r1 (14) */ 
 		NID_secp160k1, /* secp160k1 (15) */
 		NID_secp160r1, /* secp160r1 (16) */ 
 		NID_secp160r2, /* secp160r2 (17) */ 
 		NID_secp192k1, /* secp192k1 (18) */
 		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
 		NID_secp224k1, /* secp224k1 (20) */ 
 		NID_secp224r1, /* secp224r1 (21) */
 		NID_secp256k1, /* secp256k1 (22) */ 
 		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
 		NID_secp384r1, /* secp384r1 (24) */
 		NID_secp521r1  /* secp521r1 (25) */	
 	};
 
 static int pref_list[] =
 	{
 #ifndef OPENSSL_NO_EC2M
 		NID_sect571r1, /* sect571r1 (14) */ 
 		NID_sect571k1, /* sect571k1 (13) */ 
 #endif
 		NID_secp521r1, /* secp521r1 (25) */	
 #ifndef OPENSSL_NO_EC2M
 		NID_sect409k1, /* sect409k1 (11) */ 
 		NID_sect409r1, /* sect409r1 (12) */
 #endif
 		NID_secp384r1, /* secp384r1 (24) */
 #ifndef OPENSSL_NO_EC2M
 		NID_sect283k1, /* sect283k1 (9) */
 		NID_sect283r1, /* sect283r1 (10) */ 
 #endif
 		NID_secp256k1, /* secp256k1 (22) */ 
 		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
 #ifndef OPENSSL_NO_EC2M
 		NID_sect239k1, /* sect239k1 (8) */ 
 		NID_sect233k1, /* sect233k1 (6) */
 		NID_sect233r1, /* sect233r1 (7) */ 
 #endif
 		NID_secp224k1, /* secp224k1 (20) */ 
 		NID_secp224r1, /* secp224r1 (21) */
 #ifndef OPENSSL_NO_EC2M
 		NID_sect193r1, /* sect193r1 (4) */ 
 		NID_sect193r2, /* sect193r2 (5) */ 
 #endif
 		NID_secp192k1, /* secp192k1 (18) */
 		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
 #ifndef OPENSSL_NO_EC2M
 		NID_sect163k1, /* sect163k1 (1) */
 		NID_sect163r1, /* sect163r1 (2) */
 		NID_sect163r2, /* sect163r2 (3) */
 #endif
 		NID_secp160k1, /* secp160k1 (15) */
 		NID_secp160r1, /* secp160r1 (16) */ 
 		NID_secp160r2, /* secp160r2 (17) */ 
 	};
 
 int tls1_ec_curve_id2nid(int curve_id)
 	{
 	/* ECC curves from RFC 4492 */
 	if ((curve_id < 1) || ((unsigned int)curve_id >
 				sizeof(nid_list)/sizeof(nid_list[0])))
 		return 0;
 	return nid_list[curve_id-1];
 	}
 
 int tls1_ec_nid2curve_id(int nid)
 	{
 	/* ECC curves from RFC 4492 */
 	switch (nid)
 		{
 	case NID_sect163k1: /* sect163k1 (1) */
 		return 1;
 	case NID_sect163r1: /* sect163r1 (2) */
 		return 2;
 	case NID_sect163r2: /* sect163r2 (3) */
 		return 3;
 	case NID_sect193r1: /* sect193r1 (4) */ 
 		return 4;
 	case NID_sect193r2: /* sect193r2 (5) */ 
 		return 5;
 	case NID_sect233k1: /* sect233k1 (6) */
 		return 6;
 	case NID_sect233r1: /* sect233r1 (7) */ 
 		return 7;
 	case NID_sect239k1: /* sect239k1 (8) */ 
 		return 8;
 	case NID_sect283k1: /* sect283k1 (9) */
 		return 9;
 	case NID_sect283r1: /* sect283r1 (10) */ 
 		return 10;
 	case NID_sect409k1: /* sect409k1 (11) */ 
 		return 11;
 	case NID_sect409r1: /* sect409r1 (12) */
 		return 12;
 	case NID_sect571k1: /* sect571k1 (13) */ 
 		return 13;
 	case NID_sect571r1: /* sect571r1 (14) */ 
 		return 14;
 	case NID_secp160k1: /* secp160k1 (15) */
 		return 15;
 	case NID_secp160r1: /* secp160r1 (16) */ 
 		return 16;
 	case NID_secp160r2: /* secp160r2 (17) */ 
 		return 17;
 	case NID_secp192k1: /* secp192k1 (18) */
 		return 18;
 	case NID_X9_62_prime192v1: /* secp192r1 (19) */ 
 		return 19;
 	case NID_secp224k1: /* secp224k1 (20) */ 
 		return 20;
 	case NID_secp224r1: /* secp224r1 (21) */
 		return 21;
 	case NID_secp256k1: /* secp256k1 (22) */ 
 		return 22;
 	case NID_X9_62_prime256v1: /* secp256r1 (23) */ 
 		return 23;
 	case NID_secp384r1: /* secp384r1 (24) */
 		return 24;
 	case NID_secp521r1:  /* secp521r1 (25) */	
 		return 25;
 	default:
 		return 0;
 		}
 	}
 #endif /* OPENSSL_NO_EC */
 
 #ifndef OPENSSL_NO_TLSEXT
 
 /* List of supported signature algorithms and hashes. Should make this
  * customisable at some point, for now include everything we support.
  */
 
 #ifdef OPENSSL_NO_RSA
 #define tlsext_sigalg_rsa(md) /* */
 #else
 #define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
 #endif
 
 #ifdef OPENSSL_NO_DSA
 #define tlsext_sigalg_dsa(md) /* */
 #else
 #define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
 #endif
 
 #ifdef OPENSSL_NO_ECDSA
 #define tlsext_sigalg_ecdsa(md) /* */
 #else
 #define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
 #endif
 
 #define tlsext_sigalg(md) \
 		tlsext_sigalg_rsa(md) \
 		tlsext_sigalg_dsa(md) \
 		tlsext_sigalg_ecdsa(md)
 
 static unsigned char tls12_sigalgs[] = {
 #ifndef OPENSSL_NO_SHA512
 	tlsext_sigalg(TLSEXT_hash_sha512)
 	tlsext_sigalg(TLSEXT_hash_sha384)
 #endif
 #ifndef OPENSSL_NO_SHA256
 	tlsext_sigalg(TLSEXT_hash_sha256)
 	tlsext_sigalg(TLSEXT_hash_sha224)
 #endif
 #ifndef OPENSSL_NO_SHA
 	tlsext_sigalg(TLSEXT_hash_sha1)
 #endif
 };
 
 int tls12_get_req_sig_algs(SSL *s, unsigned char *p)
 	{
 	size_t slen = sizeof(tls12_sigalgs);
 	if (p)
 		memcpy(p, tls12_sigalgs, slen);
 	return (int)slen;
 	}
 
 unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit)
 	{
 	int extdatalen=0;
 	unsigned char *orig = buf;
 	unsigned char *ret = buf;
 
 	/* don't add extensions for SSLv3 unless doing secure renegotiation */
 	if (s->client_version == SSL3_VERSION
 					&& !s->s3->send_connection_binding)
 		return orig;
 
 	ret+=2;
 
 	if (ret>=limit) return NULL; /* this really never occurs, but ... */
 
  	if (s->tlsext_hostname != NULL)
 		{ 
 		/* Add TLS extension servername to the Client Hello message */
 		unsigned long size_str;
 		long lenmax; 
 
 		/* check for enough space.
 		   4 for the servername type and entension length
 		   2 for servernamelist length
 		   1 for the hostname type
 		   2 for hostname length
 		   + hostname length 
 		*/
 		   
 		if ((lenmax = limit - ret - 9) < 0 
 		    || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) 
 			return NULL;
 			
 		/* extension type and length */
 		s2n(TLSEXT_TYPE_server_name,ret); 
 		s2n(size_str+5,ret);
 		
 		/* length of servername list */
 		s2n(size_str+3,ret);
 	
 		/* hostname type, length and hostname */
 		*(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
 		s2n(size_str,ret);
 		memcpy(ret, s->tlsext_hostname, size_str);
 		ret+=size_str;
 		}
 
         /* Add RI if renegotiating */
         if (s->renegotiate)
           {
           int el;
           
           if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
               {
               SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
               return NULL;
               }
 
           if((limit - ret - 4 - el) < 0) return NULL;
           
           s2n(TLSEXT_TYPE_renegotiate,ret);
           s2n(el,ret);
 
           if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
               {
               SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
               return NULL;
               }
 
           ret += el;
         }
 
 #ifndef OPENSSL_NO_SRP
 	/* Add SRP username if there is one */
 	if (s->srp_ctx.login != NULL)
 		{ /* Add TLS extension SRP username to the Client Hello message */
 
 		int login_len = strlen(s->srp_ctx.login);	
 		if (login_len > 255 || login_len == 0)
 			{
 			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			} 
 
 		/* check for enough space.
 		   4 for the srp type type and entension length
 		   1 for the srp user identity
 		   + srp user identity length 
 		*/
 		if ((limit - ret - 5 - login_len) < 0) return NULL; 
 
 		/* fill in the extension */
 		s2n(TLSEXT_TYPE_srp,ret);
 		s2n(login_len+1,ret);
 		(*ret++) = (unsigned char) login_len;
 		memcpy(ret, s->srp_ctx.login, login_len);
 		ret+=login_len;
 		}
 #endif
 
 #ifndef OPENSSL_NO_EC
 	if (s->tlsext_ecpointformatlist != NULL)
 		{
 		/* Add TLS extension ECPointFormats to the ClientHello message */
 		long lenmax; 
 
 		if ((lenmax = limit - ret - 5) < 0) return NULL; 
 		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
 		if (s->tlsext_ecpointformatlist_length > 255)
 			{
 			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}
 		
 		s2n(TLSEXT_TYPE_ec_point_formats,ret);
 		s2n(s->tlsext_ecpointformatlist_length + 1,ret);
 		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
 		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
 		ret+=s->tlsext_ecpointformatlist_length;
 		}
 	if (s->tlsext_ellipticcurvelist != NULL)
 		{
 		/* Add TLS extension EllipticCurves to the ClientHello message */
 		long lenmax; 
 
 		if ((lenmax = limit - ret - 6) < 0) return NULL; 
 		if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL;
 		if (s->tlsext_ellipticcurvelist_length > 65532)
 			{
 			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}
 		
 		s2n(TLSEXT_TYPE_elliptic_curves,ret);
 		s2n(s->tlsext_ellipticcurvelist_length + 2, ret);
 
 		s2n(s->tlsext_ellipticcurvelist_length, ret);
 		memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
 		ret+=s->tlsext_ellipticcurvelist_length;
 		}
 #endif /* OPENSSL_NO_EC */
 
 	if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
 		{
 		int ticklen;
 		if (!s->new_session && s->session && s->session->tlsext_tick)
 			ticklen = s->session->tlsext_ticklen;
 		else if (s->session && s->tlsext_session_ticket &&
 			 s->tlsext_session_ticket->data)
 			{
 			ticklen = s->tlsext_session_ticket->length;
 			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
 			if (!s->session->tlsext_tick)
 				return NULL;
 			memcpy(s->session->tlsext_tick,
 			       s->tlsext_session_ticket->data,
 			       ticklen);
 			s->session->tlsext_ticklen = ticklen;
 			}
 		else
 			ticklen = 0;
 		if (ticklen == 0 && s->tlsext_session_ticket &&
 		    s->tlsext_session_ticket->data == NULL)
 			goto skip_ext;
 		/* Check for enough room 2 for extension type, 2 for len
  		 * rest for ticket
   		 */
 		if ((long)(limit - ret - 4 - ticklen) < 0) return NULL;
 		s2n(TLSEXT_TYPE_session_ticket,ret); 
 		s2n(ticklen,ret);
 		if (ticklen)
 			{
 			memcpy(ret, s->session->tlsext_tick, ticklen);
 			ret += ticklen;
 			}
 		}
 		skip_ext:
 
 	if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
 		{
 		if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6)
 			return NULL; 
 		s2n(TLSEXT_TYPE_signature_algorithms,ret);
 		s2n(sizeof(tls12_sigalgs) + 2, ret);
 		s2n(sizeof(tls12_sigalgs), ret);
 		memcpy(ret, tls12_sigalgs, sizeof(tls12_sigalgs));
 		ret += sizeof(tls12_sigalgs);
 		}
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
 	if (s->s3->client_opaque_prf_input != NULL &&
 	    s->version != DTLS1_VERSION)
 		{
 		size_t col = s->s3->client_opaque_prf_input_len;
 		
 		if ((long)(limit - ret - 6 - col < 0))
 			return NULL;
 		if (col > 0xFFFD) /* can't happen */
 			return NULL;
 
 		s2n(TLSEXT_TYPE_opaque_prf_input, ret); 
 		s2n(col + 2, ret);
 		s2n(col, ret);
 		memcpy(ret, s->s3->client_opaque_prf_input, col);
 		ret += col;
 		}
 #endif
 
 	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
 	    s->version != DTLS1_VERSION)
 		{
 		int i;
 		long extlen, idlen, itmp;
 		OCSP_RESPID *id;
 
 		idlen = 0;
 		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
 			{
 			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
 			itmp = i2d_OCSP_RESPID(id, NULL);
 			if (itmp <= 0)
 				return NULL;
 			idlen += itmp + 2;
 			}
 
 		if (s->tlsext_ocsp_exts)
 			{
 			extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
 			if (extlen < 0)
 				return NULL;
 			}
 		else
 			extlen = 0;
 			
 		if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
 		s2n(TLSEXT_TYPE_status_request, ret);
 		if (extlen + idlen > 0xFFF0)
 			return NULL;
 		s2n(extlen + idlen + 5, ret);
 		*(ret++) = TLSEXT_STATUSTYPE_ocsp;
 		s2n(idlen, ret);
 		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
 			{
 			/* save position of id len */
 			unsigned char *q = ret;
 			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
 			/* skip over id len */
 			ret += 2;
 			itmp = i2d_OCSP_RESPID(id, &ret);
 			/* write id len */
 			s2n(itmp, q);
 			}
 		s2n(extlen, ret);
 		if (extlen > 0)
 			i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
 		}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	/* Add Heartbeat extension */
 	if ((limit - ret - 4 - 1) < 0)
 		return NULL;
 	s2n(TLSEXT_TYPE_heartbeat,ret);
 	s2n(1,ret);
 	/* Set mode:
 	 * 1: peer may send requests
 	 * 2: peer not allowed to send requests
 	 */
 	if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
 		*(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
 	else
 		*(ret++) = SSL_TLSEXT_HB_ENABLED;
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len)
 		{
 		/* The client advertises an emtpy extension to indicate its
 		 * support for Next Protocol Negotiation */
 		if (limit - ret - 4 < 0)
 			return NULL;
 		s2n(TLSEXT_TYPE_next_proto_neg,ret);
 		s2n(0,ret);
 		}
 #endif
 
 #ifndef OPENSSL_NO_SRTP
 	if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
                 {
                 int el;
 
                 ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
                 
                 if((limit - ret - 4 - el) < 0) return NULL;
 
                 s2n(TLSEXT_TYPE_use_srtp,ret);
                 s2n(el,ret);
 
                 if(ssl_add_clienthello_use_srtp_ext(s, ret, &el, el))
 			{
 			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}
                 ret += el;
                 }
 #endif
 	/* Add padding to workaround bugs in F5 terminators.
 	 * See https://tools.ietf.org/html/draft-agl-tls-padding-03
 	 *
 	 * NB: because this code works out the length of all existing
 	 * extensions it MUST always appear last.
 	 */
 	if (s->options & SSL_OP_TLSEXT_PADDING)
 		{
 		int hlen = ret - (unsigned char *)s->init_buf->data;
 		/* The code in s23_clnt.c to build ClientHello messages
 		 * includes the 5-byte record header in the buffer, while
 		 * the code in s3_clnt.c does not.
 		 */
 		if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
 			hlen -= 5;
 		if (hlen > 0xff && hlen < 0x200)
 			{
 			hlen = 0x200 - hlen;
 			if (hlen >= 4)
 				hlen -= 4;
 			else
 				hlen = 0;
 
 			s2n(TLSEXT_TYPE_padding, ret);
 			s2n(hlen, ret);
 			memset(ret, 0, hlen);
 			ret += hlen;
 			}
 		}
 
 	if ((extdatalen = ret-orig-2)== 0) 
 		return orig;
 
 	s2n(extdatalen, orig);
 	return ret;
 	}
 
 unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit)
 	{
 	int extdatalen=0;
 	unsigned char *orig = buf;
 	unsigned char *ret = buf;
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	int next_proto_neg_seen;
 #endif
 
 	/* don't add extensions for SSLv3, unless doing secure renegotiation */
 	if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
 		return orig;
 	
 	ret+=2;
 	if (ret>=limit) return NULL; /* this really never occurs, but ... */
 
 	if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
 		{ 
 		if ((long)(limit - ret - 4) < 0) return NULL; 
 
 		s2n(TLSEXT_TYPE_server_name,ret);
 		s2n(0,ret);
 		}
 
 	if(s->s3->send_connection_binding)
         {
           int el;
           
           if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
               {
               SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
               return NULL;
               }
 
           if((limit - ret - 4 - el) < 0) return NULL;
           
           s2n(TLSEXT_TYPE_renegotiate,ret);
           s2n(el,ret);
 
           if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
               {
               SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
               return NULL;
               }
 
           ret += el;
         }
 
 #ifndef OPENSSL_NO_EC
 	if (s->tlsext_ecpointformatlist != NULL)
 		{
 		/* Add TLS extension ECPointFormats to the ServerHello message */
 		long lenmax; 
 
 		if ((lenmax = limit - ret - 5) < 0) return NULL; 
 		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
 		if (s->tlsext_ecpointformatlist_length > 255)
 			{
 			SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}
 		
 		s2n(TLSEXT_TYPE_ec_point_formats,ret);
 		s2n(s->tlsext_ecpointformatlist_length + 1,ret);
 		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
 		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
 		ret+=s->tlsext_ecpointformatlist_length;
 
 		}
 	/* Currently the server should not respond with a SupportedCurves extension */
 #endif /* OPENSSL_NO_EC */
 
 	if (s->tlsext_ticket_expected
 		&& !(SSL_get_options(s) & SSL_OP_NO_TICKET)) 
 		{ 
 		if ((long)(limit - ret - 4) < 0) return NULL; 
 		s2n(TLSEXT_TYPE_session_ticket,ret);
 		s2n(0,ret);
 		}
 
 	if (s->tlsext_status_expected)
 		{ 
 		if ((long)(limit - ret - 4) < 0) return NULL; 
 		s2n(TLSEXT_TYPE_status_request,ret);
 		s2n(0,ret);
 		}
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
 	if (s->s3->server_opaque_prf_input != NULL &&
 	    s->version != DTLS1_VERSION)
 		{
 		size_t sol = s->s3->server_opaque_prf_input_len;
 		
 		if ((long)(limit - ret - 6 - sol) < 0)
 			return NULL;
 		if (sol > 0xFFFD) /* can't happen */
 			return NULL;
 
 		s2n(TLSEXT_TYPE_opaque_prf_input, ret); 
 		s2n(sol + 2, ret);
 		s2n(sol, ret);
 		memcpy(ret, s->s3->server_opaque_prf_input, sol);
 		ret += sol;
 		}
 #endif
 
 #ifndef OPENSSL_NO_SRTP
 	if(SSL_IS_DTLS(s) && s->srtp_profile)
                 {
                 int el;
 
                 ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
                 
                 if((limit - ret - 4 - el) < 0) return NULL;
 
                 s2n(TLSEXT_TYPE_use_srtp,ret);
                 s2n(el,ret);
 
                 if(ssl_add_serverhello_use_srtp_ext(s, ret, &el, el))
 			{
 			SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}
                 ret+=el;
                 }
 #endif
 
 	if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) 
 		&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
 		{ const unsigned char cryptopro_ext[36] = {
 			0xfd, 0xe8, /*65000*/
 			0x00, 0x20, /*32 bytes length*/
 			0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 
 			0x03,   0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 
 			0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 
 			0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17};
 			if (limit-ret<36) return NULL;
 			memcpy(ret,cryptopro_ext,36);
 			ret+=36;
 
 		}
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	/* Add Heartbeat extension if we've received one */
 	if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
 		{
 		if ((limit - ret - 4 - 1) < 0)
 			return NULL;
 		s2n(TLSEXT_TYPE_heartbeat,ret);
 		s2n(1,ret);
 		/* Set mode:
 		 * 1: peer may send requests
 		 * 2: peer not allowed to send requests
 		 */
 		if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
 			*(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
 		else
 			*(ret++) = SSL_TLSEXT_HB_ENABLED;
 
 		}
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	next_proto_neg_seen = s->s3->next_proto_neg_seen;
 	s->s3->next_proto_neg_seen = 0;
 	if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb)
 		{
 		const unsigned char *npa;
 		unsigned int npalen;
 		int r;
 
 		r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen, s->ctx->next_protos_advertised_cb_arg);
 		if (r == SSL_TLSEXT_ERR_OK)
 			{
 			if ((long)(limit - ret - 4 - npalen) < 0) return NULL;
 			s2n(TLSEXT_TYPE_next_proto_neg,ret);
 			s2n(npalen,ret);
 			memcpy(ret, npa, npalen);
 			ret += npalen;
 			s->s3->next_proto_neg_seen = 1;
 			}
 		}
 #endif
 
 	if ((extdatalen = ret-orig-2)== 0) 
 		return orig;
 
 	s2n(extdatalen, orig);
 	return ret;
 	}
 
 #ifndef OPENSSL_NO_EC
 /* ssl_check_for_safari attempts to fingerprint Safari using OS X
  * SecureTransport using the TLS extension block in |d|, of length |n|.
  * Safari, since 10.6, sends exactly these extensions, in this order:
  *   SNI,
  *   elliptic_curves
  *   ec_point_formats
  *
  * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
  * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
  * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
  * 10.8..10.8.3 (which don't work).
  */
 static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) {
 	unsigned short type, size;
 	static const unsigned char kSafariExtensionsBlock[] = {
 		0x00, 0x0a,  /* elliptic_curves extension */
 		0x00, 0x08,  /* 8 bytes */
 		0x00, 0x06,  /* 6 bytes of curve ids */
 		0x00, 0x17,  /* P-256 */
 		0x00, 0x18,  /* P-384 */
 		0x00, 0x19,  /* P-521 */
 
 		0x00, 0x0b,  /* ec_point_formats */
 		0x00, 0x02,  /* 2 bytes */
 		0x01,        /* 1 point format */
 		0x00,        /* uncompressed */
 	};
 
 	/* The following is only present in TLS 1.2 */
 	static const unsigned char kSafariTLS12ExtensionsBlock[] = {
 		0x00, 0x0d,  /* signature_algorithms */
 		0x00, 0x0c,  /* 12 bytes */
 		0x00, 0x0a,  /* 10 bytes */
 		0x05, 0x01,  /* SHA-384/RSA */
 		0x04, 0x01,  /* SHA-256/RSA */
 		0x02, 0x01,  /* SHA-1/RSA */
 		0x04, 0x03,  /* SHA-256/ECDSA */
 		0x02, 0x03,  /* SHA-1/ECDSA */
 	};
 
 	if (data >= (d+n-2))
 		return;
 	data += 2;
 
 	if (data > (d+n-4))
 		return;
 	n2s(data,type);
 	n2s(data,size);
 
 	if (type != TLSEXT_TYPE_server_name)
 		return;
 
 	if (data+size > d+n)
 		return;
 	data += size;
 
 	if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
 		{
 		const size_t len1 = sizeof(kSafariExtensionsBlock);
 		const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
 
 		if (data + len1 + len2 != d+n)
 			return;
 		if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
 			return;
 		if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
 			return;
 		}
 	else
 		{
 		const size_t len = sizeof(kSafariExtensionsBlock);
 
 		if (data + len != d+n)
 			return;
 		if (memcmp(data, kSafariExtensionsBlock, len) != 0)
 			return;
 		}
 
 	s->s3->is_probably_safari = 1;
 }
 #endif /* !OPENSSL_NO_EC */
 
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
 	{
 	unsigned short type;
 	unsigned short size;
 	unsigned short len;
 	unsigned char *data = *p;
 	int renegotiate_seen = 0;
 	int sigalg_seen = 0;
 
 	s->servername_done = 0;
 	s->tlsext_status_type = -1;
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	s->s3->next_proto_neg_seen = 0;
 #endif
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
 	                       SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
 #endif
 
 #ifndef OPENSSL_NO_EC
 	if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
 		ssl_check_for_safari(s, data, d, n);
 #endif /* !OPENSSL_NO_EC */
 
 #ifndef OPENSSL_NO_SRP
 	if (s->srp_ctx.login != NULL)
 		{
 		OPENSSL_free(s->srp_ctx.login);
 		s->srp_ctx.login = NULL;
 		}
 #endif
 
 	s->srtp_profile = NULL;
 
-	if (data >= (d+n-2))
+	if (data >= (d + n - 2)) {
+	    if (data != d + n)
+		goto err;
+	    else
 		goto ri_check;
+	}
 	n2s(data,len);
 
 	if (data > (d+n-len)) 
-		goto ri_check;
+		goto err;
 
 	while (data <= (d+n-4))
 		{
 		n2s(data,type);
 		n2s(data,size);
 
 		if (data+size > (d+n))
-	   		goto ri_check;
+			goto err;
 #if 0
 		fprintf(stderr,"Received extension type %d size %d\n",type,size);
 #endif
 		if (s->tlsext_debug_cb)
 			s->tlsext_debug_cb(s, 0, type, data, size,
 						s->tlsext_debug_arg);
 /* The servername extension is treated as follows:
 
    - Only the hostname type is supported with a maximum length of 255.
    - The servername is rejected if too long or if it contains zeros,
      in which case an fatal alert is generated.
    - The servername field is maintained together with the session cache.
    - When a session is resumed, the servername call back invoked in order
      to allow the application to position itself to the right context. 
    - The servername is acknowledged if it is new for a session or when 
      it is identical to a previously used for the same session. 
      Applications can control the behaviour.  They can at any time
      set a 'desirable' servername for a new SSL object. This can be the
      case for example with HTTPS when a Host: header field is received and
      a renegotiation is requested. In this case, a possible servername
      presented in the new client hello is only acknowledged if it matches
      the value of the Host: field. 
    - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
      if they provide for changing an explicit servername context for the session,
      i.e. when the session has been established with a servername extension. 
    - On session reconnect, the servername extension may be absent. 
 
 */      
 
 		if (type == TLSEXT_TYPE_server_name)
 			{
 			unsigned char *sdata;
 			int servname_type;
 			int dsize; 
 		
 			if (size < 2) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			n2s(data,dsize);  
 			size -= 2;
 			if (dsize > size  ) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				} 
+				goto err;
 
 			sdata = data;
 			while (dsize > 3) 
 				{
 	 			servname_type = *(sdata++); 
 				n2s(sdata,len);
 				dsize -= 3;
 
 				if (len > dsize) 
-					{
-					*al = SSL_AD_DECODE_ERROR;
-					return 0;
-					}
+					goto err;
 				if (s->servername_done == 0)
 				switch (servname_type)
 					{
 				case TLSEXT_NAMETYPE_host_name:
 					if (!s->hit)
 						{
 						if(s->session->tlsext_hostname)
-							{
-							*al = SSL_AD_DECODE_ERROR;
-							return 0;
-							}
+							goto err;
 						if (len > TLSEXT_MAXLEN_host_name)
 							{
 							*al = TLS1_AD_UNRECOGNIZED_NAME;
 							return 0;
 							}
 						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)
 							{
 							*al = TLS1_AD_INTERNAL_ERROR;
 							return 0;
 							}
 						memcpy(s->session->tlsext_hostname, sdata, len);
 						s->session->tlsext_hostname[len]='\0';
 						if (strlen(s->session->tlsext_hostname) != len) {
 							OPENSSL_free(s->session->tlsext_hostname);
 							s->session->tlsext_hostname = NULL;
 							*al = TLS1_AD_UNRECOGNIZED_NAME;
 							return 0;
 						}
 						s->servername_done = 1; 
 
 						}
 					else 
 						s->servername_done = s->session->tlsext_hostname
 							&& strlen(s->session->tlsext_hostname) == len 
 							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
 					
 					break;
 
 				default:
 					break;
 					}
 				 
 				dsize -= len;
 				}
 			if (dsize != 0) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 
 			}
 #ifndef OPENSSL_NO_SRP
 		else if (type == TLSEXT_TYPE_srp)
 			{
 			if (size <= 0 || ((len = data[0])) != (size -1))
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			if (s->srp_ctx.login != NULL)
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL)
 				return -1;
 			memcpy(s->srp_ctx.login, &data[1], len);
 			s->srp_ctx.login[len]='\0';
   
 			if (strlen(s->srp_ctx.login) != len) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
+				goto err;
 				}
-			}
 #endif
 
 #ifndef OPENSSL_NO_EC
 		else if (type == TLSEXT_TYPE_ec_point_formats)
 			{
 			unsigned char *sdata = data;
 			int ecpointformatlist_length = *(sdata++);
 
 			if (ecpointformatlist_length != size - 1)
-				{
-				*al = TLS1_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			if (!s->hit)
 				{
 				if(s->session->tlsext_ecpointformatlist)
 					{
 					OPENSSL_free(s->session->tlsext_ecpointformatlist);
 					s->session->tlsext_ecpointformatlist = NULL;
 					}
 				s->session->tlsext_ecpointformatlist_length = 0;
 				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
 					{
 					*al = TLS1_AD_INTERNAL_ERROR;
 					return 0;
 					}
 				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
 				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
 				}
 #if 0
 			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length);
 			sdata = s->session->tlsext_ecpointformatlist;
 			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
 				fprintf(stderr,"%i ",*(sdata++));
 			fprintf(stderr,"\n");
 #endif
 			}
 		else if (type == TLSEXT_TYPE_elliptic_curves)
 			{
 			unsigned char *sdata = data;
 			int ellipticcurvelist_length = (*(sdata++) << 8);
 			ellipticcurvelist_length += (*(sdata++));
 
 			if (ellipticcurvelist_length != size - 2 ||
 				ellipticcurvelist_length < 1 ||
 				/* Each NamedCurve is 2 bytes. */
 				ellipticcurvelist_length & 1)
-				{
-				*al = TLS1_AD_DECODE_ERROR;
-				return 0;
-				}
+					goto err;
 			if (!s->hit)
 				{
 				if(s->session->tlsext_ellipticcurvelist)
-					{
-					*al = TLS1_AD_DECODE_ERROR;
-					return 0;
-					}
+					goto err;
+
 				s->session->tlsext_ellipticcurvelist_length = 0;
 				if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
 					{
 					*al = TLS1_AD_INTERNAL_ERROR;
 					return 0;
 					}
 				s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
 				memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
 				}
 #if 0
 			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
 			sdata = s->session->tlsext_ellipticcurvelist;
 			for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
 				fprintf(stderr,"%i ",*(sdata++));
 			fprintf(stderr,"\n");
 #endif
 			}
 #endif /* OPENSSL_NO_EC */
 #ifdef TLSEXT_TYPE_opaque_prf_input
 		else if (type == TLSEXT_TYPE_opaque_prf_input &&
 	             s->version != DTLS1_VERSION)
 			{
 			unsigned char *sdata = data;
 
 			if (size < 2)
 				{
 				*al = SSL_AD_DECODE_ERROR;
 				return 0;
 				}
 			n2s(sdata, s->s3->client_opaque_prf_input_len);
 			if (s->s3->client_opaque_prf_input_len != size - 2)
 				{
 				*al = SSL_AD_DECODE_ERROR;
 				return 0;
 				}
 
 			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
 				OPENSSL_free(s->s3->client_opaque_prf_input);
 			if (s->s3->client_opaque_prf_input_len == 0)
 				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
 			else
 				s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
 			if (s->s3->client_opaque_prf_input == NULL)
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			}
 #endif
 		else if (type == TLSEXT_TYPE_session_ticket)
 			{
 			if (s->tls_session_ticket_ext_cb &&
 			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			}
 		else if (type == TLSEXT_TYPE_renegotiate)
 			{
 			if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
 				return 0;
 			renegotiate_seen = 1;
 			}
 		else if (type == TLSEXT_TYPE_signature_algorithms)
 			{
 			int dsize;
 			if (sigalg_seen || size < 2) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			sigalg_seen = 1;
 			n2s(data,dsize);
 			size -= 2;
 			if (dsize != size || dsize & 1) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 			if (!tls1_process_sigalgs(s, data, dsize))
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
+				goto err;
 				}
-			}
 		else if (type == TLSEXT_TYPE_status_request &&
 		         s->version != DTLS1_VERSION)
 			{
 		
 			if (size < 5) 
-				{
-				*al = SSL_AD_DECODE_ERROR;
-				return 0;
-				}
+				goto err;
 
 			s->tlsext_status_type = *data++;
 			size--;
 			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
 				{
 				const unsigned char *sdata;
 				int dsize;
 				/* Read in responder_id_list */
 				n2s(data,dsize);
 				size -= 2;
 				if (dsize > size  ) 
-					{
-					*al = SSL_AD_DECODE_ERROR;
-					return 0;
-					}
+					goto err;
 				while (dsize > 0)
 					{
 					OCSP_RESPID *id;
 					int idsize;
 					if (dsize < 4)
-						{
-						*al = SSL_AD_DECODE_ERROR;
-						return 0;
-						}
+						goto err;
 					n2s(data, idsize);
 					dsize -= 2 + idsize;
 					size -= 2 + idsize;
 					if (dsize < 0)
-						{
-						*al = SSL_AD_DECODE_ERROR;
-						return 0;
-						}
+						goto err;
 					sdata = data;
 					data += idsize;
 					id = d2i_OCSP_RESPID(NULL,
 								&sdata, idsize);
 					if (!id)
-						{
-						*al = SSL_AD_DECODE_ERROR;
-						return 0;
-						}
+						goto err;
 					if (data != sdata)
 						{
 						OCSP_RESPID_free(id);
-						*al = SSL_AD_DECODE_ERROR;
-						return 0;
+                        goto err;
 						}
 					if (!s->tlsext_ocsp_ids
 						&& !(s->tlsext_ocsp_ids =
 						sk_OCSP_RESPID_new_null()))
 						{
 						OCSP_RESPID_free(id);
 						*al = SSL_AD_INTERNAL_ERROR;
 						return 0;
 						}
 					if (!sk_OCSP_RESPID_push(
 							s->tlsext_ocsp_ids, id))
 						{
 						OCSP_RESPID_free(id);
 						*al = SSL_AD_INTERNAL_ERROR;
 						return 0;
 						}
 					}
 
 				/* Read in request_extensions */
 				if (size < 2)
-					{
-					*al = SSL_AD_DECODE_ERROR;
-					return 0;
-					}
+					goto err;
 				n2s(data,dsize);
 				size -= 2;
 				if (dsize != size)
-					{
-					*al = SSL_AD_DECODE_ERROR;
-					return 0;
-					}
+					goto err;
 				sdata = data;
 				if (dsize > 0)
 					{
 					if (s->tlsext_ocsp_exts)
 						{
 						sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
 									   X509_EXTENSION_free);
 						}
 
 					s->tlsext_ocsp_exts =
 						d2i_X509_EXTENSIONS(NULL,
 							&sdata, dsize);
 					if (!s->tlsext_ocsp_exts
 						|| (data + dsize != sdata))
-						{
-						*al = SSL_AD_DECODE_ERROR;
-						return 0;
+							goto err;
 						}
 					}
-				}
 				/* We don't know what to do with any other type
  			 	* so ignore it.
  			 	*/
 				else
 					s->tlsext_status_type = -1;
 			}
 #ifndef OPENSSL_NO_HEARTBEATS
 		else if (type == TLSEXT_TYPE_heartbeat)
 			{
 			switch(data[0])
 				{
 				case 0x01:	/* Client allows us to send HB requests */
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
 							break;
 				case 0x02:	/* Client doesn't accept HB requests */
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
 							break;
 				default:	*al = SSL_AD_ILLEGAL_PARAMETER;
 							return 0;
 				}
 			}
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
 		else if (type == TLSEXT_TYPE_next_proto_neg &&
 			 s->s3->tmp.finish_md_len == 0)
 			{
 			/* We shouldn't accept this extension on a
 			 * renegotiation.
 			 *
 			 * s->new_session will be set on renegotiation, but we
 			 * probably shouldn't rely that it couldn't be set on
 			 * the initial renegotation too in certain cases (when
 			 * there's some other reason to disallow resuming an
 			 * earlier session -- the current code won't be doing
 			 * anything like that, but this might change).
 
 			 * A valid sign that there's been a previous handshake
 			 * in this connection is if s->s3->tmp.finish_md_len >
 			 * 0.  (We are talking about a check that will happen
 			 * in the Hello protocol round, well before a new
 			 * Finished message could have been computed.) */
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
 
 		/* session ticket processed earlier */
 #ifndef OPENSSL_NO_SRTP
 		else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
 			 && type == TLSEXT_TYPE_use_srtp)
 			{
 			if(ssl_parse_clienthello_use_srtp_ext(s, data, size,
 							      al))
 				return 0;
 			}
 #endif
 
 		data+=size;
 		}
 				
+    /* Spurious data on the end */
+    if (data != d + n)
+        goto err;
+
 	*p = data;
 
 	ri_check:
 
 	/* Need RI if renegotiating */
 
 	if (!renegotiate_seen && s->renegotiate &&
 		!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
 		{
 		*al = SSL_AD_HANDSHAKE_FAILURE;
 	 	SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
 				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
 		return 0;
 		}
 
 	return 1;
-	}
+err:
+    *al = SSL_AD_DECODE_ERROR;
+    return 0;
+}
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 /* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
  * elements of zero length are allowed and the set of elements must exactly fill
  * the length of the block. */
 static char ssl_next_proto_validate(unsigned char *d, unsigned len)
 	{
 	unsigned int off = 0;
 
 	while (off < len)
 		{
 		if (d[off] == 0)
 			return 0;
 		off += d[off];
 		off++;
 		}
 
 	return off == len;
 	}
 #endif
 
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
 	{
 	unsigned short length;
 	unsigned short type;
 	unsigned short size;
 	unsigned char *data = *p;
 	int tlsext_servername = 0;
 	int renegotiate_seen = 0;
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	s->s3->next_proto_neg_seen = 0;
 #endif
 	s->tlsext_ticket_expected = 0;
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
 	                       SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
 #endif
 
 	if (data >= (d+n-2))
 		goto ri_check;
 
 	n2s(data,length);
 	if (data+length != d+n)
 		{
 		*al = SSL_AD_DECODE_ERROR;
 		return 0;
 		}
 
 	while(data <= (d+n-4))
 		{
 		n2s(data,type);
 		n2s(data,size);
 
 		if (data+size > (d+n))
 	   		goto ri_check;
 
 		if (s->tlsext_debug_cb)
 			s->tlsext_debug_cb(s, 1, type, data, size,
 						s->tlsext_debug_arg);
 
 		if (type == TLSEXT_TYPE_server_name)
 			{
 			if (s->tlsext_hostname == NULL || size > 0)
 				{
 				*al = TLS1_AD_UNRECOGNIZED_NAME;
 				return 0;
 				}
 			tlsext_servername = 1;   
 			}
 
 #ifndef OPENSSL_NO_EC
 		else if (type == TLSEXT_TYPE_ec_point_formats)
 			{
 			unsigned char *sdata = data;
 			int ecpointformatlist_length = *(sdata++);
 
 			if (ecpointformatlist_length != size - 1 || 
 				ecpointformatlist_length < 1)
 				{
 				*al = TLS1_AD_DECODE_ERROR;
 				return 0;
 				}
 			if (!s->hit)
 				{
 				s->session->tlsext_ecpointformatlist_length = 0;
 				if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
 				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
 					{
 					*al = TLS1_AD_INTERNAL_ERROR;
 					return 0;
 					}
 				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
 				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
 				}
 #if 0
 			fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
 			sdata = s->session->tlsext_ecpointformatlist;
 			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
 				fprintf(stderr,"%i ",*(sdata++));
 			fprintf(stderr,"\n");
 #endif
 			}
 #endif /* OPENSSL_NO_EC */
 
 		else if (type == TLSEXT_TYPE_session_ticket)
 			{
 			if (s->tls_session_ticket_ext_cb &&
 			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
 				|| (size > 0))
 				{
 				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
 				return 0;
 				}
 			s->tlsext_ticket_expected = 1;
 			}
 #ifdef TLSEXT_TYPE_opaque_prf_input
 		else if (type == TLSEXT_TYPE_opaque_prf_input &&
 	             s->version != DTLS1_VERSION)
 			{
 			unsigned char *sdata = data;
 
 			if (size < 2)
 				{
 				*al = SSL_AD_DECODE_ERROR;
 				return 0;
 				}
 			n2s(sdata, s->s3->server_opaque_prf_input_len);
 			if (s->s3->server_opaque_prf_input_len != size - 2)
 				{
 				*al = SSL_AD_DECODE_ERROR;
 				return 0;
 				}
 			
 			if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
 				OPENSSL_free(s->s3->server_opaque_prf_input);
 			if (s->s3->server_opaque_prf_input_len == 0)
 				s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
 			else
 				s->s3->server_opaque_prf_input = BUF_memdup(sdata, s->s3->server_opaque_prf_input_len);
 
 			if (s->s3->server_opaque_prf_input == NULL)
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			}
 #endif
 		else if (type == TLSEXT_TYPE_status_request &&
 		         s->version != DTLS1_VERSION)
 			{
 			/* MUST be empty and only sent if we've requested
 			 * a status request message.
 			 */ 
 			if ((s->tlsext_status_type == -1) || (size > 0))
 				{
 				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
 				return 0;
 				}
 			/* Set flag to expect CertificateStatus message */
 			s->tlsext_status_expected = 1;
 			}
 #ifndef OPENSSL_NO_NEXTPROTONEG
 		else if (type == TLSEXT_TYPE_next_proto_neg &&
 			 s->s3->tmp.finish_md_len == 0)
 			{
 			unsigned char *selected;
 			unsigned char selected_len;
 
 			/* We must have requested it. */
 			if (s->ctx->next_proto_select_cb == NULL)
 				{
 				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
 				return 0;
 				}
 			/* The data must be valid */
 			if (!ssl_next_proto_validate(data, size))
 				{
 				*al = TLS1_AD_DECODE_ERROR;
 				return 0;
 				}
 			if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, data, size, s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK)
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			s->next_proto_negotiated = OPENSSL_malloc(selected_len);
 			if (!s->next_proto_negotiated)
 				{
 				*al = TLS1_AD_INTERNAL_ERROR;
 				return 0;
 				}
 			memcpy(s->next_proto_negotiated, selected, selected_len);
 			s->next_proto_negotiated_len = selected_len;
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
 		else if (type == TLSEXT_TYPE_renegotiate)
 			{
 			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
 				return 0;
 			renegotiate_seen = 1;
 			}
 #ifndef OPENSSL_NO_HEARTBEATS
 		else if (type == TLSEXT_TYPE_heartbeat)
 			{
 			switch(data[0])
 				{
 				case 0x01:	/* Server allows us to send HB requests */
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
 							break;
 				case 0x02:	/* Server doesn't accept HB requests */
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
 							s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
 							break;
 				default:	*al = SSL_AD_ILLEGAL_PARAMETER;
 							return 0;
 				}
 			}
 #endif
 #ifndef OPENSSL_NO_SRTP
 		else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp)
 			{
                         if(ssl_parse_serverhello_use_srtp_ext(s, data, size,
 							      al))
                                 return 0;
 			}
 #endif
 
 		data+=size;		
 		}
 
 	if (data != d+n)
 		{
 		*al = SSL_AD_DECODE_ERROR;
 		return 0;
 		}
 
 	if (!s->hit && tlsext_servername == 1)
 		{
  		if (s->tlsext_hostname)
 			{
 			if (s->session->tlsext_hostname == NULL)
 				{
 				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
 				if (!s->session->tlsext_hostname)
 					{
 					*al = SSL_AD_UNRECOGNIZED_NAME;
 					return 0;
 					}
 				}
 			else 
 				{
 				*al = SSL_AD_DECODE_ERROR;
 				return 0;
 				}
 			}
 		}
 
 	*p = data;
 
 	ri_check:
 
 	/* Determine if we need to see RI. Strictly speaking if we want to
 	 * avoid an attack we should *always* see RI even on initial server
 	 * hello because the client doesn't see any renegotiation during an
 	 * attack. However this would mean we could not connect to any server
 	 * which doesn't support RI so for the immediate future tolerate RI
 	 * absence on initial connect only.
 	 */
 	if (!renegotiate_seen
 		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
 		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
 		{
 		*al = SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
 				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
 		return 0;
 		}
 
 	return 1;
 	}
 
 
 int ssl_prepare_clienthello_tlsext(SSL *s)
 	{
 #ifndef OPENSSL_NO_EC
 	/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats 
 	 * and elliptic curves we support.
 	 */
 	int using_ecc = 0;
 	int i;
 	unsigned char *j;
 	unsigned long alg_k, alg_a;
 	STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
 
 	for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
 		{
 		SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
 
 		alg_k = c->algorithm_mkey;
 		alg_a = c->algorithm_auth;
 		if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA)))
 			{
 			using_ecc = 1;
 			break;
 			}
 		}
 	using_ecc = using_ecc && (s->version >= TLS1_VERSION);
 	if (using_ecc)
 		{
 		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
 		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
 			{
 			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
 			return -1;
 			}
 		s->tlsext_ecpointformatlist_length = 3;
 		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
 		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
 		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
 
 		/* we support all named elliptic curves in RFC 4492 */
 		if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
 		s->tlsext_ellipticcurvelist_length = sizeof(pref_list)/sizeof(pref_list[0]) * 2;
 		if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
 			{
 			s->tlsext_ellipticcurvelist_length = 0;
 			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
 			return -1;
 			}
 		for (i = 0, j = s->tlsext_ellipticcurvelist; (unsigned int)i <
 				sizeof(pref_list)/sizeof(pref_list[0]); i++)
 			{
 			int id = tls1_ec_nid2curve_id(pref_list[i]);
 			s2n(id,j);
 			}
 		}
 #endif /* OPENSSL_NO_EC */
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
  	{
 		int r = 1;
 	
 		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
 			{
 			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
 			if (!r)
 				return -1;
 			}
 
 		if (s->tlsext_opaque_prf_input != NULL)
 			{
 			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
 				OPENSSL_free(s->s3->client_opaque_prf_input);
 
 			if (s->tlsext_opaque_prf_input_len == 0)
 				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
 			else
 				s->s3->client_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
 			if (s->s3->client_opaque_prf_input == NULL)
 				{
 				SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
 				return -1;
 				}
 			s->s3->client_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
 			}
 
 		if (r == 2)
 			/* at callback's request, insist on receiving an appropriate server opaque PRF input */
 			s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
 	}
 #endif
 
 	return 1;
 	}
 
 int ssl_prepare_serverhello_tlsext(SSL *s)
 	{
 #ifndef OPENSSL_NO_EC
 	/* If we are server and using an ECC cipher suite, send the point formats we support 
 	 * if the client sent us an ECPointsFormat extension.  Note that the server is not
 	 * supposed to send an EllipticCurves extension.
 	 */
 
 	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 	int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
 	using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
 	
 	if (using_ecc)
 		{
 		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
 		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
 			{
 			SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
 			return -1;
 			}
 		s->tlsext_ecpointformatlist_length = 3;
 		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
 		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
 		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
 		}
 #endif /* OPENSSL_NO_EC */
 
 	return 1;
 	}
 
 int ssl_check_clienthello_tlsext_early(SSL *s)
 	{
 	int ret=SSL_TLSEXT_ERR_NOACK;
 	int al = SSL_AD_UNRECOGNIZED_NAME;
 
 #ifndef OPENSSL_NO_EC
 	/* The handling of the ECPointFormats extension is done elsewhere, namely in 
 	 * ssl3_choose_cipher in s3_lib.c.
 	 */
 	/* The handling of the EllipticCurves extension is done elsewhere, namely in 
 	 * ssl3_choose_cipher in s3_lib.c.
 	 */
 #endif
 
 	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
 		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
 	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
 		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
  	{
 		/* This sort of belongs into ssl_prepare_serverhello_tlsext(),
 		 * but we might be sending an alert in response to the client hello,
 		 * so this has to happen here in
 		 * ssl_check_clienthello_tlsext_early(). */
 
 		int r = 1;
 	
 		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
 			{
 			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
 			if (!r)
 				{
 				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 				al = SSL_AD_INTERNAL_ERROR;
 				goto err;
 				}
 			}
 
 		if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
 			OPENSSL_free(s->s3->server_opaque_prf_input);
 		s->s3->server_opaque_prf_input = NULL;
 
 		if (s->tlsext_opaque_prf_input != NULL)
 			{
 			if (s->s3->client_opaque_prf_input != NULL &&
 				s->s3->client_opaque_prf_input_len == s->tlsext_opaque_prf_input_len)
 				{
 				/* can only use this extension if we have a server opaque PRF input
 				 * of the same length as the client opaque PRF input! */
 
 				if (s->tlsext_opaque_prf_input_len == 0)
 					s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
 				else
 					s->s3->server_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
 				if (s->s3->server_opaque_prf_input == NULL)
 					{
 					ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 					al = SSL_AD_INTERNAL_ERROR;
 					goto err;
 					}
 				s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
 				}
 			}
 
 		if (r == 2 && s->s3->server_opaque_prf_input == NULL)
 			{
 			/* The callback wants to enforce use of the extension,
 			 * but we can't do that with the client opaque PRF input;
 			 * abort the handshake.
 			 */
 			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 			al = SSL_AD_HANDSHAKE_FAILURE;
 			}
 	}
 
  err:
 #endif
 	switch (ret)
 		{
 		case SSL_TLSEXT_ERR_ALERT_FATAL:
 			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
 			return -1;
 
 		case SSL_TLSEXT_ERR_ALERT_WARNING:
 			ssl3_send_alert(s,SSL3_AL_WARNING,al);
 			return 1; 
 					
 		case SSL_TLSEXT_ERR_NOACK:
 			s->servername_done=0;
 			default:
 		return 1;
 		}
 	}
 
 int ssl_check_clienthello_tlsext_late(SSL *s)
 	{
 	int ret = SSL_TLSEXT_ERR_OK;
 	int al;
 
 	/* If status request then ask callback what to do.
  	 * Note: this must be called after servername callbacks in case 
  	 * the certificate has changed, and must be called after the cipher
 	 * has been chosen because this may influence which certificate is sent
  	 */
 	if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
 		{
 		int r;
 		CERT_PKEY *certpkey;
 		certpkey = ssl_get_server_send_pkey(s);
 		/* If no certificate can't return certificate status */
 		if (certpkey == NULL)
 			{
 			s->tlsext_status_expected = 0;
 			return 1;
 			}
 		/* Set current certificate to one we will use so
 		 * SSL_get_certificate et al can pick it up.
 		 */
 		s->cert->key = certpkey;
 		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 		switch (r)
 			{
 			/* We don't want to send a status request response */
 			case SSL_TLSEXT_ERR_NOACK:
 				s->tlsext_status_expected = 0;
 				break;
 			/* status request response should be sent */
 			case SSL_TLSEXT_ERR_OK:
 				if (s->tlsext_ocsp_resp)
 					s->tlsext_status_expected = 1;
 				else
 					s->tlsext_status_expected = 0;
 				break;
 			/* something bad happened */
 			case SSL_TLSEXT_ERR_ALERT_FATAL:
 				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 				al = SSL_AD_INTERNAL_ERROR;
 				goto err;
 			}
 		}
 	else
 		s->tlsext_status_expected = 0;
 
  err:
 	switch (ret)
 		{
 		case SSL_TLSEXT_ERR_ALERT_FATAL:
 			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
 			return -1;
 
 		case SSL_TLSEXT_ERR_ALERT_WARNING:
 			ssl3_send_alert(s,SSL3_AL_WARNING,al);
 			return 1; 
 
 		default:
 			return 1;
 		}
 	}
 
 int ssl_check_serverhello_tlsext(SSL *s)
 	{
 	int ret=SSL_TLSEXT_ERR_NOACK;
 	int al = SSL_AD_UNRECOGNIZED_NAME;
 
 #ifndef OPENSSL_NO_EC
 	/* If we are client and using an elliptic curve cryptography cipher
 	 * suite, then if server returns an EC point formats lists extension
 	 * it must contain uncompressed.
 	 */
 	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 	if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) && 
 	    (s->session->tlsext_ecpointformatlist != NULL) && (s->session->tlsext_ecpointformatlist_length > 0) && 
 	    ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA)))
 		{
 		/* we are using an ECC cipher */
 		size_t i;
 		unsigned char *list;
 		int found_uncompressed = 0;
 		list = s->session->tlsext_ecpointformatlist;
 		for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
 			{
 			if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed)
 				{
 				found_uncompressed = 1;
 				break;
 				}
 			}
 		if (!found_uncompressed)
 			{
 			SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
 			return -1;
 			}
 		}
 	ret = SSL_TLSEXT_ERR_OK;
 #endif /* OPENSSL_NO_EC */
 
 	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
 		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
 	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
 		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
 	if (s->s3->server_opaque_prf_input_len > 0)
 		{
 		/* This case may indicate that we, as a client, want to insist on using opaque PRF inputs.
 		 * So first verify that we really have a value from the server too. */
 
 		if (s->s3->server_opaque_prf_input == NULL)
 			{
 			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 			al = SSL_AD_HANDSHAKE_FAILURE;
 			}
 		
 		/* Anytime the server *has* sent an opaque PRF input, we need to check
 		 * that we have a client opaque PRF input of the same size. */
 		if (s->s3->client_opaque_prf_input == NULL ||
 		    s->s3->client_opaque_prf_input_len != s->s3->server_opaque_prf_input_len)
 			{
 			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 			al = SSL_AD_ILLEGAL_PARAMETER;
 			}
 		}
 #endif
 
 	/* If we've requested certificate status and we wont get one
  	 * tell the callback
  	 */
 	if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
 			&& s->ctx && s->ctx->tlsext_status_cb)
 		{
 		int r;
 		/* Set resp to NULL, resplen to -1 so callback knows
  		 * there is no response.
  		 */
 		if (s->tlsext_ocsp_resp)
 			{
 			OPENSSL_free(s->tlsext_ocsp_resp);
 			s->tlsext_ocsp_resp = NULL;
 			}
 		s->tlsext_ocsp_resplen = -1;
 		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 		if (r == 0)
 			{
 			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 			}
 		if (r < 0)
 			{
 			al = SSL_AD_INTERNAL_ERROR;
 			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 			}
 		}
 
 	switch (ret)
 		{
 		case SSL_TLSEXT_ERR_ALERT_FATAL:
 			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
 			return -1;
 
 		case SSL_TLSEXT_ERR_ALERT_WARNING:
 			ssl3_send_alert(s,SSL3_AL_WARNING,al);
 			return 1; 
 					
 		case SSL_TLSEXT_ERR_NOACK:
 			s->servername_done=0;
 			default:
 		return 1;
 		}
 	}
 
 /* Since the server cache lookup is done early on in the processing of the
  * ClientHello, and other operations depend on the result, we need to handle
  * any TLS session ticket extension at the same time.
  *
  *   session_id: points at the session ID in the ClientHello. This code will
  *       read past the end of this in order to parse out the session ticket
  *       extension, if any.
  *   len: the length of the session ID.
  *   limit: a pointer to the first byte after the ClientHello.
  *   ret: (output) on return, if a ticket was decrypted, then this is set to
  *       point to the resulting session.
  *
  * If s->tls_session_secret_cb is set then we are expecting a pre-shared key
  * ciphersuite, in which case we have no use for session tickets and one will
  * never be decrypted, nor will s->tlsext_ticket_expected be set to 1.
  *
  * Returns:
  *   -1: fatal error, either from parsing or decrypting the ticket.
  *    0: no ticket was found (or was ignored, based on settings).
  *    1: a zero length extension was found, indicating that the client supports
  *       session tickets but doesn't currently have one to offer.
  *    2: either s->tls_session_secret_cb was set, or a ticket was offered but
  *       couldn't be decrypted because of a non-fatal error.
  *    3: a ticket was successfully decrypted and *ret was set.
  *
  * Side effects:
  *   Sets s->tlsext_ticket_expected to 1 if the server will have to issue
  *   a new session ticket to the client because the client indicated support
  *   (and s->tls_session_secret_cb is NULL) but the client either doesn't have
  *   a session ticket or we couldn't use the one it gave us, or if
  *   s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
  *   Otherwise, s->tlsext_ticket_expected is set to 0.
  */
 int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 			const unsigned char *limit, SSL_SESSION **ret)
 	{
 	/* Point after session ID in client hello */
 	const unsigned char *p = session_id + len;
 	unsigned short i;
 
 	*ret = NULL;
 	s->tlsext_ticket_expected = 0;
 
 	/* If tickets disabled behave as if no ticket present
 	 * to permit stateful resumption.
 	 */
 	if (SSL_get_options(s) & SSL_OP_NO_TICKET)
 		return 0;
 	if ((s->version <= SSL3_VERSION) || !limit)
 		return 0;
 	if (p >= limit)
 		return -1;
 	/* Skip past DTLS cookie */
 	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
 		{
 		i = *(p++);
 		p+= i;
 		if (p >= limit)
 			return -1;
 		}
 	/* Skip past cipher list */
 	n2s(p, i);
 	p+= i;
 	if (p >= limit)
 		return -1;
 	/* Skip past compression algorithm list */
 	i = *(p++);
 	p += i;
 	if (p > limit)
 		return -1;
 	/* Now at start of extensions */
 	if ((p + 2) >= limit)
 		return 0;
 	n2s(p, i);
 	while ((p + 4) <= limit)
 		{
 		unsigned short type, size;
 		n2s(p, type);
 		n2s(p, size);
 		if (p + size > limit)
 			return 0;
 		if (type == TLSEXT_TYPE_session_ticket)
 			{
 			int r;
 			if (size == 0)
 				{
 				/* The client will accept a ticket but doesn't
 				 * currently have one. */
 				s->tlsext_ticket_expected = 1;
 				return 1;
 				}
 			if (s->tls_session_secret_cb)
 				{
 				/* Indicate that the ticket couldn't be
 				 * decrypted rather than generating the session
 				 * from ticket now, trigger abbreviated
 				 * handshake based on external mechanism to
 				 * calculate the master secret later. */
 				return 2;
 				}
 			r = tls_decrypt_ticket(s, p, size, session_id, len, ret);
 			switch (r)
 				{
 				case 2: /* ticket couldn't be decrypted */
 					s->tlsext_ticket_expected = 1;
 					return 2;
 				case 3: /* ticket was decrypted */
 					return r;
 				case 4: /* ticket decrypted but need to renew */
 					s->tlsext_ticket_expected = 1;
 					return 3;
 				default: /* fatal error */
 					return -1;
 				}
 			}
 		p += size;
 		}
 	return 0;
 	}
 
 /* tls_decrypt_ticket attempts to decrypt a session ticket.
  *
  *   etick: points to the body of the session ticket extension.
  *   eticklen: the length of the session tickets extenion.
  *   sess_id: points at the session ID.
  *   sesslen: the length of the session ID.
  *   psess: (output) on return, if a ticket was decrypted, then this is set to
  *       point to the resulting session.
  *
  * Returns:
  *   -1: fatal error, either from parsing or decrypting the ticket.
  *    2: the ticket couldn't be decrypted.
  *    3: a ticket was successfully decrypted and *psess was set.
  *    4: same as 3, but the ticket needs to be renewed.
  */
 static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
 				const unsigned char *sess_id, int sesslen,
 				SSL_SESSION **psess)
 	{
 	SSL_SESSION *sess;
 	unsigned char *sdec;
 	const unsigned char *p;
 	int slen, mlen, renew_ticket = 0;
 	unsigned char tick_hmac[EVP_MAX_MD_SIZE];
 	HMAC_CTX hctx;
 	EVP_CIPHER_CTX ctx;
 	SSL_CTX *tctx = s->initial_ctx;
 	/* Need at least keyname + iv + some encrypted data */
 	if (eticklen < 48)
 		return 2;
 	/* Initialize session ticket encryption and HMAC contexts */
 	HMAC_CTX_init(&hctx);
 	EVP_CIPHER_CTX_init(&ctx);
 	if (tctx->tlsext_ticket_key_cb)
 		{
 		unsigned char *nctick = (unsigned char *)etick;
 		int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
 							&ctx, &hctx, 0);
 		if (rv < 0)
 			return -1;
 		if (rv == 0)
 			return 2;
 		if (rv == 2)
 			renew_ticket = 1;
 		}
 	else
 		{
 		/* Check key name matches */
 		if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
 			return 2;
 		HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
 					tlsext_tick_md(), NULL);
 		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
 				tctx->tlsext_tick_aes_key, etick + 16);
 		}
 	/* Attempt to process session ticket, first conduct sanity and
 	 * integrity checks on ticket.
 	 */
 	mlen = HMAC_size(&hctx);
 	if (mlen < 0)
 		{
 		EVP_CIPHER_CTX_cleanup(&ctx);
 		return -1;
 		}
 	eticklen -= mlen;
 	/* Check HMAC of encrypted ticket */
 	HMAC_Update(&hctx, etick, eticklen);
 	HMAC_Final(&hctx, tick_hmac, NULL);
 	HMAC_CTX_cleanup(&hctx);
 	if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
 		{
 		EVP_CIPHER_CTX_cleanup(&ctx);
 		return 2;
 		}
 	/* Attempt to decrypt session data */
 	/* Move p after IV to start of encrypted ticket, update length */
 	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
 	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
 	sdec = OPENSSL_malloc(eticklen);
 	if (!sdec)
 		{
 		EVP_CIPHER_CTX_cleanup(&ctx);
 		return -1;
 		}
 	EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
 	if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
 		{
 		EVP_CIPHER_CTX_cleanup(&ctx);
 		OPENSSL_free(sdec);
 		return 2;
 		}
 	slen += mlen;
 	EVP_CIPHER_CTX_cleanup(&ctx);
 	p = sdec;
 
 	sess = d2i_SSL_SESSION(NULL, &p, slen);
 	OPENSSL_free(sdec);
 	if (sess)
 		{
 		/* The session ID, if non-empty, is used by some clients to
 		 * detect that the ticket has been accepted. So we copy it to
 		 * the session structure. If it is empty set length to zero
 		 * as required by standard.
 		 */
 		if (sesslen)
 			memcpy(sess->session_id, sess_id, sesslen);
 		sess->session_id_length = sesslen;
 		*psess = sess;
 		if (renew_ticket)
 			return 4;
 		else
 			return 3;
 		}
         ERR_clear_error();
 	/* For session parse failure, indicate that we need to send a new
 	 * ticket. */
 	return 2;
 	}
 
 /* Tables to translate from NIDs to TLS v1.2 ids */
 
 typedef struct 
 	{
 	int nid;
 	int id;
 	} tls12_lookup;
 
 static tls12_lookup tls12_md[] = {
 #ifndef OPENSSL_NO_MD5
 	{NID_md5, TLSEXT_hash_md5},
 #endif
 #ifndef OPENSSL_NO_SHA
 	{NID_sha1, TLSEXT_hash_sha1},
 #endif
 #ifndef OPENSSL_NO_SHA256
 	{NID_sha224, TLSEXT_hash_sha224},
 	{NID_sha256, TLSEXT_hash_sha256},
 #endif
 #ifndef OPENSSL_NO_SHA512
 	{NID_sha384, TLSEXT_hash_sha384},
 	{NID_sha512, TLSEXT_hash_sha512}
 #endif
 };
 
 static tls12_lookup tls12_sig[] = {
 #ifndef OPENSSL_NO_RSA
 	{EVP_PKEY_RSA, TLSEXT_signature_rsa},
 #endif
 #ifndef OPENSSL_NO_DSA
 	{EVP_PKEY_DSA, TLSEXT_signature_dsa},
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	{EVP_PKEY_EC, TLSEXT_signature_ecdsa}
 #endif
 };
 
 static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
 	{
 	size_t i;
 	for (i = 0; i < tlen; i++)
 		{
 		if (table[i].nid == nid)
 			return table[i].id;
 		}
 	return -1;
 	}
 #if 0
 static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
 	{
 	size_t i;
 	for (i = 0; i < tlen; i++)
 		{
 		if (table[i].id == id)
 			return table[i].nid;
 		}
 	return -1;
 	}
 #endif
 
 int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
 	{
 	int sig_id, md_id;
 	if (!md)
 		return 0;
 	md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
 				sizeof(tls12_md)/sizeof(tls12_lookup));
 	if (md_id == -1)
 		return 0;
 	sig_id = tls12_get_sigid(pk);
 	if (sig_id == -1)
 		return 0;
 	p[0] = (unsigned char)md_id;
 	p[1] = (unsigned char)sig_id;
 	return 1;
 	}
 
 int tls12_get_sigid(const EVP_PKEY *pk)
 	{
 	return tls12_find_id(pk->type, tls12_sig,
 				sizeof(tls12_sig)/sizeof(tls12_lookup));
 	}
 
 const EVP_MD *tls12_get_hash(unsigned char hash_alg)
 	{
 	switch(hash_alg)
 		{
 #ifndef OPENSSL_NO_SHA
 		case TLSEXT_hash_sha1:
 		return EVP_sha1();
 #endif
 #ifndef OPENSSL_NO_SHA256
 		case TLSEXT_hash_sha224:
 		return EVP_sha224();
 
 		case TLSEXT_hash_sha256:
 		return EVP_sha256();
 #endif
 #ifndef OPENSSL_NO_SHA512
 		case TLSEXT_hash_sha384:
 		return EVP_sha384();
 
 		case TLSEXT_hash_sha512:
 		return EVP_sha512();
 #endif
 		default:
 		return NULL;
 
 		}
 	}
 
 /* Set preferred digest for each key type */
 
 int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 	{
 	int i, idx;
 	const EVP_MD *md;
 	CERT *c = s->cert;
 	/* Extension ignored for TLS versions below 1.2 */
 	if (TLS1_get_version(s) < TLS1_2_VERSION)
 		return 1;
 	/* Should never happen */
 	if (!c)
 		return 0;
 
 	c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
 	c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
 	c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
 	c->pkeys[SSL_PKEY_ECC].digest = NULL;
 
 	for (i = 0; i < dsize; i += 2)
 		{
 		unsigned char hash_alg = data[i], sig_alg = data[i+1];
 
 		switch(sig_alg)
 			{
 #ifndef OPENSSL_NO_RSA
 			case TLSEXT_signature_rsa:
 			idx = SSL_PKEY_RSA_SIGN;
 			break;
 #endif
 #ifndef OPENSSL_NO_DSA
 			case TLSEXT_signature_dsa:
 			idx = SSL_PKEY_DSA_SIGN;
 			break;
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			case TLSEXT_signature_ecdsa:
 			idx = SSL_PKEY_ECC;
 			break;
 #endif
 			default:
 			continue;
 			}
 
 		if (c->pkeys[idx].digest == NULL)
 			{
 			md = tls12_get_hash(hash_alg);
 			if (md)
 				{
 				c->pkeys[idx].digest = md;
 				if (idx == SSL_PKEY_RSA_SIGN)
 					c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
 				}
 			}
 
 		}
 
 
 	/* Set any remaining keys to default values. NOTE: if alg is not
 	 * supported it stays as NULL.
 	 */
 #ifndef OPENSSL_NO_DSA
 	if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
 		c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
 #endif
 #ifndef OPENSSL_NO_RSA
 	if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
 		{
 		c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
 		c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
 		}
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	if (!c->pkeys[SSL_PKEY_ECC].digest)
 		c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
 #endif
 	return 1;
 	}
 
 #endif
 
 #ifndef OPENSSL_NO_HEARTBEATS
 int
 tls1_process_heartbeat(SSL *s)
 	{
 	unsigned char *p = &s->s3->rrec.data[0], *pl;
 	unsigned short hbtype;
 	unsigned int payload;
 	unsigned int padding = 16; /* Use minimum padding */
 
 	if (s->msg_callback)
 		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
 			&s->s3->rrec.data[0], s->s3->rrec.length,
 			s, s->msg_callback_arg);
 
 	/* Read type and payload length first */
 	if (1 + 2 + 16 > s->s3->rrec.length)
 		return 0; /* silently discard */
 	hbtype = *p++;
 	n2s(p, payload);
 	if (1 + 2 + payload + 16 > s->s3->rrec.length)
 		return 0; /* silently discard per RFC 6520 sec. 4 */
 	pl = p;
 
 	if (hbtype == TLS1_HB_REQUEST)
 		{
 		unsigned char *buffer, *bp;
 		int r;
 
 		/* Allocate memory for the response, size is 1 bytes
 		 * message type, plus 2 bytes payload length, plus
 		 * payload, plus padding
 		 */
 		buffer = OPENSSL_malloc(1 + 2 + payload + padding);
 		bp = buffer;
 		
 		/* Enter response type, length and copy payload */
 		*bp++ = TLS1_HB_RESPONSE;
 		s2n(payload, bp);
 		memcpy(bp, pl, payload);
 		bp += payload;
 		/* Random padding */
 		RAND_pseudo_bytes(bp, padding);
 
 		r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
 
 		if (r >= 0 && s->msg_callback)
 			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
 				buffer, 3 + payload + padding,
 				s, s->msg_callback_arg);
 
 		OPENSSL_free(buffer);
 
 		if (r < 0)
 			return r;
 		}
 	else if (hbtype == TLS1_HB_RESPONSE)
 		{
 		unsigned int seq;
 		
 		/* We only send sequence numbers (2 bytes unsigned int),
 		 * and 16 random bytes, so we just try to read the
 		 * sequence number */
 		n2s(pl, seq);
 		
 		if (payload == 18 && seq == s->tlsext_hb_seq)
 			{
 			s->tlsext_hb_seq++;
 			s->tlsext_hb_pending = 0;
 			}
 		}
 
 	return 0;
 	}
 
 int
 tls1_heartbeat(SSL *s)
 	{
 	unsigned char *buf, *p;
 	int ret;
 	unsigned int payload = 18; /* Sequence number + random bytes */
 	unsigned int padding = 16; /* Use minimum padding */
 
 	/* Only send if peer supports and accepts HB requests... */
 	if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
 	    s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS)
 		{
 		SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
 		return -1;
 		}
 
 	/* ...and there is none in flight yet... */
 	if (s->tlsext_hb_pending)
 		{
 		SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PENDING);
 		return -1;
 		}
 		
 	/* ...and no handshake in progress. */
 	if (SSL_in_init(s) || s->in_handshake)
 		{
 		SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_UNEXPECTED_MESSAGE);
 		return -1;
 		}
 		
 	/* Check if padding is too long, payload and padding
 	 * must not exceed 2^14 - 3 = 16381 bytes in total.
 	 */
 	OPENSSL_assert(payload + padding <= 16381);
 
 	/* Create HeartBeat message, we just use a sequence number
 	 * as payload to distuingish different messages and add
 	 * some random stuff.
 	 *  - Message Type, 1 byte
 	 *  - Payload Length, 2 bytes (unsigned int)
 	 *  - Payload, the sequence number (2 bytes uint)
 	 *  - Payload, random bytes (16 bytes uint)
 	 *  - Padding
 	 */
 	buf = OPENSSL_malloc(1 + 2 + payload + padding);
 	p = buf;
 	/* Message Type */
 	*p++ = TLS1_HB_REQUEST;
 	/* Payload length (18 bytes here) */
 	s2n(payload, p);
 	/* Sequence number */
 	s2n(s->tlsext_hb_seq, p);
 	/* 16 random bytes */
 	RAND_pseudo_bytes(p, 16);
 	p += 16;
 	/* Random padding */
 	RAND_pseudo_bytes(p, padding);
 
 	ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
 	if (ret >= 0)
 		{
 		if (s->msg_callback)
 			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
 				buf, 3 + payload + padding,
 				s, s->msg_callback_arg);
 
 		s->tlsext_hb_pending = 1;
 		}
 		
 	OPENSSL_free(buf);
 
 	return ret;
 	}
 #endif
Index: releng/10.1/sys/conf/newvers.sh
===================================================================
--- releng/10.1/sys/conf/newvers.sh	(revision 284294)
+++ releng/10.1/sys/conf/newvers.sh	(revision 284295)
@@ -1,224 +1,224 @@
 #!/bin/sh -
 #
 # Copyright (c) 1984, 1986, 1990, 1993
 #	The Regents of the University of California.  All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
 # 1. Redistributions of source code must retain the above copyright
 #    notice, this list of conditions and the following disclaimer.
 # 2. Redistributions in binary form must reproduce the above copyright
 #    notice, this list of conditions and the following disclaimer in the
 #    documentation and/or other materials provided with the distribution.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
 #
 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
 #	@(#)newvers.sh	8.1 (Berkeley) 4/20/94
 # $FreeBSD$
 
 TYPE="FreeBSD"
 REVISION="10.1"
-BRANCH="RELEASE-p11"
+BRANCH="RELEASE-p12"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi
 RELEASE="${REVISION}-${BRANCH}"
 VERSION="${TYPE} ${RELEASE}"
 
 if [ "X${SYSDIR}" = "X" ]; then
     SYSDIR=$(dirname $0)/..
 fi
 
 if [ "X${PARAMFILE}" != "X" ]; then
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${PARAMFILE})
 else
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${SYSDIR}/sys/param.h)
 fi
 
 b=share/examples/etc/bsd-style-copyright
 year=`date '+%Y'`
 # look for copyright template
 for bsd_copyright in ../$b ../../$b ../../../$b /usr/src/$b /usr/$b
 do
 	if [ -r "$bsd_copyright" ]; then
 		COPYRIGHT=`sed \
 		    -e "s/\[year\]/1992-$year/" \
 		    -e 's/\[your name here\]\.* /The FreeBSD Project./' \
 		    -e 's/\[your name\]\.*/The FreeBSD Project./' \
 		    -e '/\[id for your version control system, if any\]/d' \
 		    $bsd_copyright` 
 		break
 	fi
 done
 
 # no copyright found, use a dummy
 if [ X"$COPYRIGHT" = X ]; then
 	COPYRIGHT="/*-
  * Copyright (c) 1992-$year The FreeBSD Project.
  * All rights reserved.
  *
  */"
 fi
 
 # add newline
 COPYRIGHT="$COPYRIGHT
 "
 
 LC_ALL=C; export LC_ALL
 if [ ! -r version ]
 then
 	echo 0 > version
 fi
 
 touch version
 v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
 i=`${MAKE:-make} -V KERN_IDENT`
 compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
 
 for dir in /usr/bin /usr/local/bin; do
 	if [ ! -z "${svnversion}" ] ; then
 		break
 	fi
 	if [ -x "${dir}/svnversion" ] && [ -z ${svnversion} ] ; then
 		# Run svnversion from ${dir} on this script; if return code
 		# is not zero, the checkout might not be compatible with the
 		# svnversion being used.
 		${dir}/svnversion $(realpath ${0}) >/dev/null 2>&1
 		if [ $? -eq 0 ]; then
 			svnversion=${dir}/svnversion
 			break
 		fi
 	fi
 done
 
 if [ -z "${svnversion}" ] && [ -x /usr/bin/svnliteversion ] ; then
 	/usr/bin/svnliteversion $(realpath ${0}) >/dev/null 2>&1
 	if [ $? -eq 0 ]; then
 		svnversion=/usr/bin/svnliteversion
 	else
 		svnversion=
 	fi
 fi
 
 for dir in /usr/bin /usr/local/bin; do
 	if [ -x "${dir}/p4" ] && [ -z ${p4_cmd} ] ; then
 		p4_cmd=${dir}/p4
 	fi
 done
 if [ -d "${SYSDIR}/../.git" ] ; then
 	for dir in /usr/bin /usr/local/bin; do
 		if [ -x "${dir}/git" ] ; then
 			git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git"
 			break
 		fi
 	done
 fi
 
 if [ -d "${SYSDIR}/../.hg" ] ; then
 	for dir in /usr/bin /usr/local/bin; do
 		if [ -x "${dir}/hg" ] ; then
 			hg_cmd="${dir}/hg -R ${SYSDIR}/.."
 			break
 		fi
 	done
 fi
 
 if [ -n "$svnversion" ] ; then
 	svn=`cd ${SYSDIR} && $svnversion 2>/dev/null`
 	case "$svn" in
 	[0-9]*)	svn=" r${svn}" ;;
 	*)	unset svn ;;
 	esac
 fi
 
 if [ -n "$git_cmd" ] ; then
 	git=`$git_cmd rev-parse --verify --short HEAD 2>/dev/null`
 	svn=`$git_cmd svn find-rev $git 2>/dev/null`
 	if [ -n "$svn" ] ; then
 		svn=" r${svn}"
 		git="=${git}"
 	else
 		svn=`$git_cmd log | fgrep 'git-svn-id:' | head -1 | \
 		     sed -n 's/^.*@\([0-9][0-9]*\).*$/\1/p'`
 		if [ -z "$svn" ] ; then
 			svn=`$git_cmd log --format='format:%N' | \
 			     grep '^svn ' | head -1 | \
 			     sed -n 's/^.*revision=\([0-9][0-9]*\).*$/\1/p'`
 		fi
 		if [ -n "$svn" ] ; then
 			svn=" r${svn}"
 			git="+${git}"
 		else
 			git=" ${git}"
 		fi
 	fi
 	git_b=`$git_cmd rev-parse --abbrev-ref HEAD`
 	if [ -n "$git_b" ] ; then
 		git="${git}(${git_b})"
 	fi
 	if $git_cmd --work-tree=${SYSDIR}/.. diff-index \
 	    --name-only HEAD | read dummy; then
 		git="${git}-dirty"
 	fi
 fi
 
 if [ -n "$p4_cmd" ] ; then
 	p4version=`cd ${SYSDIR} && $p4_cmd changes -m1 "./...#have" 2>&1 | \
 		awk '{ print $2 }'`
 	case "$p4version" in
 	[0-9]*)
 		p4version=" ${p4version}"
 		p4opened=`cd ${SYSDIR} && $p4_cmd opened ./... 2>&1`
 		case "$p4opened" in
 		File*) ;;
 		//*)	p4version="${p4version}+edit" ;;
 		esac
 		;;
 	*)	unset p4version ;;
 	esac
 fi
 
 if [ -n "$hg_cmd" ] ; then
 	hg=`$hg_cmd id 2>/dev/null`
 	svn=`$hg_cmd svn info 2>/dev/null | \
 		awk -F': ' '/Revision/ { print $2 }'`
 	if [ -n "$svn" ] ; then
 		svn=" r${svn}"
 	fi
 	if [ -n "$hg" ] ; then
 		hg=" ${hg}"
 	fi
 fi
 
 cat << EOF > vers.c
 $COPYRIGHT
 #define SCCSSTR "@(#)${VERSION} #${v}${svn}${git}${hg}${p4version}: ${t}"
 #define VERSTR "${VERSION} #${v}${svn}${git}${hg}${p4version}: ${t}\\n    ${u}@${h}:${d}\\n"
 #define RELSTR "${RELEASE}"
 
 char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR;
 char version[sizeof(VERSTR) > 256 ? sizeof(VERSTR) : 256] = VERSTR;
 char compiler_version[] = "${compiler_v}";
 char ostype[] = "${TYPE}";
 char osrelease[sizeof(RELSTR) > 32 ? sizeof(RELSTR) : 32] = RELSTR;
 int osreldate = ${RELDATE};
 char kern_ident[] = "${i}";
 EOF
 
 echo $((v + 1)) > version
Index: releng/8.4/UPDATING
===================================================================
--- releng/8.4/UPDATING	(revision 284294)
+++ releng/8.4/UPDATING	(revision 284295)
@@ -1,2058 +1,2061 @@
 Updating Information for FreeBSD current users
 
 This file is maintained and copyrighted by M. Warner Losh
 .  See end of file for further details.  For commonly
 done items, please see the COMMON ITEMS: section later in the file.
 
 Items affecting the ports and packages system can be found in
 /usr/ports/UPDATING.  Please read that file before running
 portupgrade.
 
 NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW ON IA64 OR SUN4V:
 	For ia64 the INVARIANTS and INVARIANT_SUPPORT kernel options
 	were left in the GENERIC kernel because the kernel does not
 	work properly without them.  For sun4v all of the normal kernel
 	debugging tools present in HEAD were left in place because
 	sun4v support still needs work to become production ready.
 
+20150612:	p30	FreeBSD-SA-15:10.openssl
+	Fix multiple vulnerabilities in OpenSSL.  [SA-15:10]
+
 20150609:	p29	FreeBSD-EN-15:06.file
 
 	Updated base system file(1) to 5.22 to address multiple denial
 	of service issues.
 
 20150513:	p28	FreeBSD-EN-15:04.freebsd-update
 
 	Fix bug with freebsd-update(8) that does not ensure the previous
 	upgrade was completed. [EN-15:04]
 
 20150407:	p27	FreeBSD-SA-15:04.igmp [revised]
 			FreeBSD-SA-15:07.ntp
 			FreeBSD-SA-15:09.ipv6
 
 	Improved patch for SA-15:04.igmp.
 
 	Fix multiple vulnerabilities of ntp. [SA-15:07]
 
 	Fix Denial of Service with IPv6 Router Advertisements. [SA-15:09]
 
 20150320:       p26
         Fix patch for SA-15:06.openssl.
 
 20150319:	p25	FreeBSD-SA-15:06.openssl
 	Fix multiple vulnerabilities in OpenSSL.  [SA-15:06]
 
 20150225:	p24	FreeBSD-SA-15:04.igmp
 			FreeBSD-SA-15:05.bind
 			FreeBSD-EN-15:01.vt
 			FreeBSD-EN-15:02.openssl
 			FreeBSD-EN-15:03.freebsd-update
 
 	Fix integer overflow in IGMP protocol. [SA-15:04]
 
 	Fix BIND remote denial of service vulnerability. [SA-15:05]
 
 	Fix vt(4) crash with improper ioctl parameters. [EN-15:01]
 
 	Updated base system OpenSSL to 0.9.8zd. [EN-15:02]
 
 	Fix freebsd-update libraries update ordering issue. [EN-15:03]
 
 20150127:	p23	FreeBSD-SA-15:02.kmem
 			FreeBSD-SA-15:03.sctp
 
 	Fix SCTP SCTP_SS_VALUE kernel memory corruption and disclosure
 	vulnerability.  [SA-15:02]
 
 	Fix SCTP stream reset vulnerability.  [SA-15:03]
 
 20150114:	p22	FreeBSD-SA-15:01.openssl
 	Fix multiple vulnerabilities in OpenSSL.  [SA-15:01]
 
 20141223:	p21	FreeBSD-SA-14:31.ntp
 			FreeBSD-EN-14:13.freebsd-update
 
 	Fix multiple vulnerabilities in NTP suite.  [SA-14:31]
 	Fix directory deletion issue in freebsd-update.	 [EN-14:13]
 
 20141210:	p20	FreeBSD-SA-14:28.file
 			FreeBSD-SA-14:29.bind
 
 	Fix multiple vulnerabilities in file(1) and libmagic(3).
 	[SA-14:28]
 
 	Fix BIND remote denial of service vulnerability. [SA-14:29]
 
 20141104:	p19	FreeBSD-SA-14:25.setlogin
 			FreeBSD-SA-14:26.ftp
 			FreeBSD-EN-14:12.zfs
 
 	Fix kernel stack disclosure in setlogin(2) / getlogin(2).
 	[SA-14:25]
 
 	Fix remote command execution in ftp(1). [SA-14:26]
 
 	Fix NFSv4 and ZFS cache consistency issue. [EN-14:12]
 
 20141022:	p18	FreeBSD-EN-14:10.tzdata
 
 	Time zone data file update. [EN-14:10]
 
 20141021:	p17	FreeBSD-SA-14:21.routed
 			FreeBSD-SA-14:23.openssl
 
 	Fix routed(8) remote denial of service vulnerability. [SA-14:21]
 
 	Fix OpenSSL multiple vulnerabilities. [SA-14:23]
 
 20140916:	p16	FreeBSD-SA-14:19.tcp
 	Fix Denial of Service in TCP packet processing. [SA-14:19]
 
 20140909:	p15	FreeBSD-SA-14:18.openssl
 	Fix OpenSSL multiple vulnerabilities. [SA-14:18]
 
 20140708:	p14	FreeBSD-SA-14:17.kmem
 			FreeBSD-EN-14:09.jail
 	Fix kernel memory disclosure in control messages and SCTP
 	notifications. [SA-14:17]
 
 	Fix jail fails to start if WITHOUT_INET/WITHOUT_INET6 is use.
 	[EN-14:09]
 
 20140624:	p13	FreeBSD-SA-14:16.file
 			FreeBSD-EN-14:08.heimdal
 
 	Fix multiple vulnerabilities in file(1) and libmagic(3).
 	[SA-14:16]
 
 	Fix gss_pseudo_random interoperability issue. [EN-14:08]
 
 20140605:	p12	FreeBSD-SA-14:14.openssl
 	Fix OpenSSL multiple vulnerabilities. [SA-14:14]
 
 20140603:	p11	FreeBSD-SA-14:11.sendmail
 			FreeBSD-SA-14:12.ktrace
 			FreeBSD-EN-14:06.exec
 
 	Fix sendmail improper close-on-exec flag handling. [SA-14:11]
 
 	Fix ktrace memory disclosure. [SA-14:12]
 
 	Fix triple-fault when executing from a threaded process.
 	[EN-14:06]
 
 20140513:	p10	FreeBSD-EN-14:03.pkg
 			FreeBSD-EN-14:04.kldxref
 
 	Add pkg bootstrapping, configuration and public keys. [EN-14:03]
 
 	Improve build repeatability for kldxref(8). [EN-14:04]
 
 20140430:	p9	FreeBSD-SA-14:08.tcp
 
         Fix TCP reassembly vulnerability. [SA-14:08]
 
 20140408:	p8	FreeBSD-SA-14:05.nfsserver
 			FreeBSD-SA-14:06.openssl
 	Fix deadlock in the NFS server. [SA-14:05]
 
 	Fix for ECDSA Cache Side-channel Attack in OpenSSL. [SA-14:06]
 
 20140114:	p7	FreeBSD-SA-14:01.bsnmpd
 			FreeBSD-SA-14:02.ntpd
 			FreeBSD-SA-14:04.bind
 			FreeBSD-EN-14:01.random
 			FreeBSD-EN-14:02.mmap
 	Fix bsnmpd remote denial of service vulnerability. [SA-14:01]
 
 	Fix ntpd distributed reflection Denial of Service
 	vulnerability. [SA-14:02]
 
 	Fix BIND remote denial of service vulnerability. [SA-14:04]
 
 	Disable hardware RNGs by default. [EN-14:01]
 
 	Fix incorrect coalescing of stack entry with mmap. [EN-14:02]
 
 20131128:	p6	FreeBSD-EN-13:05.freebsd-update
 	Fix error in patch for FreeBSD-EN-13:04.freebsd-update.
 
 20131026:	p5	FreeBSD-EN-13:04.freebsd-update
 	Fix multiple freebsd-update bugs that break upgrading to
 	FreeBSD 10.0.
 
 20130910:	p4	FreeBSD-SA-13:12.ifioctl
 			FreeBSD-SA-13:13.nullfs
 
 	In IPv6 and NetATM, stop SIOCSIFADDR, SIOCSIFBRDADDR,
 	SIOCSIFDSTADDR and SIOCSIFNETMASK at the socket layer rather
 	than pass them on to the link layer without validation or
 	credential checks.  [SA-13:12]
 
 	Prevent cross-mount hardlinks between different nullfs mounts
 	of the same underlying filesystem.  [SA-13:13]
 
 20130822:	p3	FreeBSD-SA-13:09.ip_multicast
 			FreeBSD-SA-13:10.sctp
 	Fix an integer overflow in computing the size of a temporary buffer
 	can result in a buffer which is too small for the requested
 	operation. [13:09]
 
 	Fix a bug that could lead to kernel memory disclosure with
 	SCTP state cookie. [13:10]
 
 20130726:	p2	FreeBSD-SA-13:07.bind
 	Fix Denial of Service vulnerability in named(8).
 
 20130628:	p1	FreeBSD-EN-13:01.fxp
 			FreeBSD-EN-13:02.vtnet
 	Fix a problem where dhclient(8) utility tries to initilaize an
 	fxp(4) forever because the driver resets the controller chip
 	twice upon initialization. [EN-13:01]
 
 	Fix a problem where frames sent to additional MAC addresses are
 	not forwarded to the vtnet(4) interface. [EN-13:02]
 
 20130429:
 	Fix a bug that allows NFS clients to issue READDIR on files.
 
 20130225:
 	A new compression method (lz4) has been merged.  Please refer to
 	zpool-features(7) for more information.
 
 	Please refer to the "ZFS notes" section of this file for information
 	on upgrading boot ZFS pools.
 
 20121130:
 	A new version of ZFS (pool version 5000) has been merged to 8-STABLE.
 	Starting with this version the old system of ZFS pool versioning
 	is superseded by "feature flags". This concept enables forward
 	compatibility against certain future changes in functionality of ZFS
 	pools. The first two read-only compatible "feature flags" for ZFS
 	pools are "com.delphix:async_destroy" and "com.delphix:empty_bpobj".
 	For more information read the new zpool-features(7) manual page.
 	Please refer to the "ZFS notes" section of this file for information
 	on upgrading boot ZFS pools.
 
 20121018:
 	WITH_CTF can now be specified in src.conf (not recommended, there
 	are some problems with static executables), make.conf (would also
 	affect ports which do not use GNU make and do not override the
 	compile targets) or in the kernel config (via "makeoptions
 	WITH_CTF=yes").
 	When WITH_CTF was specified there before this was silently ignored,
 	so make sure that WITH_CTF is not used in places which could lead
 	to unwanted behavior.
 
 20120913:
 	The random(4) support for the VIA hardware random number
 	generator (`PADLOCK') is no longer enabled unconditionally.
 	Add the PADLOCK_RNG option in the custom kernel config if
 	needed.  The GENERIC kernels on i386 and amd64 do include the
 	option, so the change only affects the custom kernel
 	configurations.
 
 20120727:
 	The sparc64 ZFS loader has been changed to no longer try to auto-
 	detect ZFS providers based on diskN aliases but now requires these
 	to be explicitly listed in the OFW boot-device environment variable.
 
 20120411:
 	8.3-RELEASE.
 
 20120106:
 	A new VOP_ADVISE() was added to support posix_fadvise(2).  All
 	filesystem modules must be recompiled.
 
 20111116:
 	A new VOP_ALLOCATE() was added to support posix_fallocate(2).  All
 	filesystem modules must be recompiled.
 
 20111101:
 	The broken amd(4) driver has been replaced with esp(4) in the amd64,
 	i386 and pc98 GENERIC kernel configuration files.
 
 20110606:
 	A new version of ZFS (version 28) has been merged.
 	This version does not depend on a python library and the
 	sysutils/py-zfs port is not used anymore.
 	For upgrading your boot pool, please read "ZFS notes"
 	in the COMMON ITEMS: section later in this file.
 
 20110428:
 	IPsec's HMAC_SHA256-512 support has been fixed to be RFC4868
 	compliant, and will now use half of hash for authentication.
 	This will break interoperability with all stacks (including all
 	older FreeBSD versions) who implement
 	draft-ietf-ipsec-ciph-sha-256-00 (they use 96 bits of hash for
 	authentication).
 	The only workaround with such peers is to use another HMAC
 	algorithm for IPsec ("phase 2") authentication.
 
 20110221:
 	8.2-RELEASE.
 
 20101126:
 	New version of minidump format for amd64 architecture was
 	introduced in r215872.  To analyze vmcore files produced by
 	kernels at or after this version you will need updated userland,
 	libkvm actually, that is able to handle the new version.
 
 20101022:
 	A workaround for a fixed ld bug has been removed in kernel code,
 	so make sure that your system ld is built from sources after
 	revision 211583 from 2010-08-21 (r210245 from 2010-07-19 if
 	building stable/8 kernel on head, r211584 from 2010-08-21 for
 	stable/7).  A symptom of incorrect ld version is
 	different addresses for set_pcpu section and __start_set_pcpu
 	symbol in kernel and/or modules.
 
 20100915:
 	A new version of ZFS (version 15) has been merged.
 	This version uses a python library for the following subcommands:
 	zfs allow, zfs unallow, zfs groupspace, zfs userspace.
 	For full functionality of these commands the following port must
 	be installed: sysutils/py-zfs
 
 20100720:
 	8.1-RELEASE.
 
 20100502:
 	The config(8) command has been updated to maintain compatibility
 	with config files from 8.0-RELEASE.  You will need a new version
 	of config to build kernels (this version can be used from 8.0-RELEASE
 	forward).  The buildworld target will generate it, so following
 	the instructions in this file for updating will work glitch-free.
 	Merely doing a make buildkernel without first doing a make buildworld
 	(or kernel-toolchain), or attempting to build a kernel using
 	traidtional methods will generate a config version warning, indicating
 	you should update.
 
 20100408:
 	The rc.firewall and rc.firewall6 were unified, and
 	rc.firewall6 and rc.d/ip6fw were removed.
 	According to the removal of rc.d/ip6fw, ipv6_firewall_* rc
 	variables are obsoleted.  Instead, the following new rc
 	variables are added to rc.d/ipfw:
 
 		firewall_client_net_ipv6, firewall_simple_iif_ipv6,
 		firewall_simple_inet_ipv6, firewall_simple_oif_ipv6,
 		firewall_simple_onet_ipv6
 
 	The meanings correspond to the relevant IPv4 variables.
 
 20100417:
 	COMPAT_IA32 has been added as an alias for COMPAT_FREEBSD32.  A new
 	version of config(8) is required.  The error message when you hit this
 	condition is confusing (COMPAT_FREEBSD32 duplicate option), when it
 	should really say "your config is too old to compile this new kernel."
 
 20100406:
 	The kernel option COMPAT_IA32 has been replaced with COMPAT_FREEBSD32
 	to allow 32-bit compatibility on non-x86 platforms. All kernel
 	configurations on amd64 and ia64 platforms using these options must
 	be modified accordingly.
 
 20100125:
 	Introduce the kernel thread "deadlock resolver" (which can be enabled
 	via the DEADLKRES option, see NOTES for more details) and the
 	sleepq_type() function for sleepqueues.
 
 20091125:
 	8.0-RELEASE.
 
 20090929:
 	802.11s D3.03 support was committed. This is incompatible with
 	the previous code, which was based on D3.0.
 
 20090915:
 	ZFS snapshots are now mounted with MNT_IGNORE flag. Use -v option for
 	mount(8) and -a option for df(1) to see them.
 
 20090813:
 	Remove the option STOP_NMI.  The default action is now to use NMI
 	only for KDB via the newly introduced function stop_cpus_hard()
 	and maintain stop_cpus() to just use a normal IPI_STOP on ia32
 	and amd64.
 
 20090803:
 	RELENG_8 branched.
 
 20090719:
 	Bump the shared library version numbers for all libraries that
 	do not use symbol versioning as part of the 8.0-RELEASE cycle.
 	Bump __FreeBSD_version to 800105.
 
 20090714:
 	Due to changes in the implementation of virtual network stack
 	support, all network-related kernel modules must be recompiled.
 	As this change breaks the ABI, bump __FreeBSD_version to 800104.
 
 20090713:
 	The TOE interface to the TCP syncache has been modified to remove struct
 	tcpopt () from the ABI of the network stack.  The
 	cxgb driver is the only TOE consumer affected by this change, and needs
 	to be recompiled along with the kernel. As this change breaks the ABI,
 	bump __FreeBSD_version to 800103.
 
 20090712:
 	Padding has been added to struct tcpcb, sackhint and tcpstat in
 	 to facilitate future MFCs and bug fixes whilst
 	maintainig the ABI. However, this change breaks the ABI, so bump
 	__FreeBSD_version to 800102. User space tools that rely on the size of
 	any of these structs (e.g. sockstat) need to be recompiled.
 
 20090630:
 	The NFS_LEGACYRPC option has been removed along with the old
 	kernel RPC implementation that this option selected. Kernel
 	configurations may need to be adjusted.
 
 20090629:
 	The network interface device nodes at /dev/net/ have
 	been removed.  All ioctl operations can be performed the normal
 	way using routing sockets.  The kqueue functionality can
 	generally be replaced with routing sockets.
 
 20090628:
 	The documentation from the FreeBSD Documentation Project
 	(Handbook, FAQ, etc.) is now installed via packages by
 	sysinstall(8) and under the /usr/local/share/doc/freebsd
 	directory instead of /usr/share/doc.
 
 20090624:
 	The ABI of various structures related to the SYSV IPC API have
 	been changed.  As a result, the COMPAT_FREEBSD[456] and COMPAT_43
 	kernel options now all require COMPAT_FREEBSD7.
 	Bump __FreeBSD_version to 800100.
 
 20090622:
 	Layout of struct vnet has changed as routing related variables
 	were moved to their own Vimage module. Modules need to be
 	recompiled.  Bump __FreeBSD_version to 800099.
 
 20090619:
 	NGROUPS_MAX and NGROUPS have been increased from 16 to 1023
 	and 1024 respectively.  As long as no more than 16 groups per
 	process are used, no changes should be visible.  When more
 	than 16 groups are used, old binaries may fail if they call
 	getgroups() or getgrouplist() with statically sized storage.
 	Recompiling will work around this, but applications should be
 	modified to use dynamically allocated storage for group arrays
 	as POSIX.1-2008 does not cap an implementation's number of
 	supported groups at NGROUPS_MAX+1 as previous versions did.
 
 	NFS and portalfs mounts may also be affected as the list of
 	groups is truncated to 16.  Users of NFS who use more than 16
 	groups, should take care that negative group permissions are not
 	used on the exported file systems as they will not be reliable
 	unless a GSSAPI based authentication method is used.
 
 20090616:
 	The compiling option ADAPTIVE_LOCKMGRS has been introduced.
 	This option compiles in the support for adaptive spinning for lockmgrs
 	which want to enable it.  The lockinit() function now accepts the
 	flag LK_ADAPTIVE in order to make the lock object subject to
 	adaptive spinning when both held in write and read mode.
 
 20090613:
 	The layout of the structure returned by IEEE80211_IOC_STA_INFO
 	has changed.  User applications that use this ioctl need to be
 	rebuilt.
 
 20090611:
 	The layout of struct thread has changed.  Kernel and modules
 	need to be rebuilt.
 
 20090608:
 	The layout of structs ifnet, domain, protosw and vnet_net has
 	changed.  Kernel modules need to be rebuilt.
 	Bump __FreeBSD_version to 800097.
 
 20090602:
 	window(1) has been removed from the base system. It can now be
 	installed from ports. The port is called misc/window.
 
 20090601:
 	The way we are storing and accessing `routing table' entries
 	has changed. Programs reading the FIB, like netstat, need to
 	be re-compiled.
 
 20090601:
 	A new netisr implementation has been added for FreeBSD 8.  Network
 	file system modules, such as igmp, ipdivert, and others, should be
 	rebuilt.
 	Bump __FreeBSD_version to 800096.
 
 20090530:
 	Remove the tunable/sysctl debug.mpsafevfs as its initial purpose
 	is no more valid.
 
 20090530:
 	Add VOP_ACCESSX(9).  File system modules need to be rebuilt.
 	Bump __FreeBSD_version to 800094.
 
 20090529:
 	Add mnt_xflag field to 'struct mount'.  File system modules
 	need to be rebuilt.
 	Bump __FreeBSD_version to 800093.
 
 20090528:
 	The compiling option ADAPTIVE_SX has been retired while it has been
 	introduced the option NO_ADAPTIVE_SX which handles the reversed logic.
 	The KPI for sx_init_flags() changes as accepting flags:
 	SX_ADAPTIVESPIN flag has been retired while the SX_NOADAPTIVE flag
 	has been introduced in order to handle the reversed logic.
 	Bump __FreeBSD_version to 800092.
 
 20090527:
 	Add support for hierarchical jails.  Remove global securelevel.
 	Bump __FreeBSD_version to 800091.
 
 20090523:
 	The layout of struct vnet_net has changed, therefore modules
 	need to be rebuilt.
 	Bump __FreeBSD_version to 800090.
 
 20090523:
 	The newly imported zic(8) produces a new format in the
 	output. Please run tzsetup(8) to install the newly created
 	data to /etc/localtime.
 
 20090520:
 	The sysctl tree for the usb stack has renamed from hw.usb2.* to
 	hw.usb.* and is now consistent again with previous releases.
 
 20090520:
 	802.11 monitor mode support was revised and driver api's
 	were changed.  Drivers dependent on net80211 now support
 	DLT_IEEE802_11_RADIO instead of DLT_IEEE802_11.  No
 	user-visible data structures were changed but applications
 	that use DLT_IEEE802_11 may require changes.
 	Bump __FreeBSD_version to 800088.
 
 20090430:
 	The layout of the following structs has changed: sysctl_oid,
 	socket, ifnet, inpcbinfo, tcpcb, syncache_head, vnet_inet,
 	vnet_inet6 and vnet_ipfw.  Most modules need to be rebuild or
 	panics may be experienced.  World rebuild is required for
 	correctly checking networking state from userland.
 	Bump __FreeBSD_version to 800085.
 
 20090429:
 	MLDv2 and Source-Specific Multicast (SSM) have been merged
 	to the IPv6 stack. VIMAGE hooks are in but not yet used.
 	The implementation of SSM within FreeBSD's IPv6 stack closely
 	follows the IPv4 implementation.
 
 	For kernel developers:
 
 	* The most important changes are that the ip6_output() and
 	  ip6_input() paths no longer take the IN6_MULTI_LOCK,
 	  and this lock has been downgraded to a non-recursive mutex.
 
 	* As with the changes to the IPv4 stack to support SSM, filtering
 	  of inbound multicast traffic must now be performed by transport
 	  protocols within the IPv6 stack. This does not apply to TCP and
 	  SCTP, however, it does apply to UDP in IPv6 and raw IPv6.
 
 	* The KPIs used by IPv6 multicast are similar to those used by
 	  the IPv4 stack, with the following differences:
 	   * im6o_mc_filter() is analogous to imo_multicast_filter().
 	   * The legacy KAME entry points in6_joingroup and in6_leavegroup()
 	     are shimmed to in6_mc_join() and in6_mc_leave() respectively.
 	   * IN6_LOOKUP_MULTI() has been deprecated and removed.
 	   * IPv6 relies on MLD for the DAD mechanism. KAME's internal KPIs
 	     for MLDv1 have an additional 'timer' argument which is used to
 	     jitter the initial membership report for the solicited-node
 	     multicast membership on-link.
 	   * This is not strictly needed for MLDv2, which already jitters
 	     its report transmissions.  However, the 'timer' argument is
 	     preserved in case MLDv1 is active on the interface.
 
 	* The KAME linked-list based IPv6 membership implementation has
 	  been refactored to use a vector similar to that used by the IPv4
 	  stack.
 	  Code which maintains a list of its own multicast memberships
 	  internally, e.g. carp, has been updated to reflect the new
 	  semantics.
 
 	* There is a known Lock Order Reversal (LOR) due to in6_setscope()
 	  acquiring the IF_AFDATA_LOCK and being called within ip6_output().
 	  Whilst MLDv2 tries to avoid this otherwise benign LOR, it is an
 	  implementation constraint which needs to be addressed in HEAD.
 
 	For application developers:
 
 	* The changes are broadly similar to those made for the IPv4
 	  stack.
 
 	* The use of IPv4 and IPv6 multicast socket options on the same
 	  socket, using mapped addresses, HAS NOT been tested or supported.
 
 	* There are a number of issues with the implementation of various
 	  IPv6 multicast APIs which need to be resolved in the API surface
 	  before the implementation is fully compatible with KAME userland
 	  use, and these are mostly to do with interface index treatment.
 
 	* The literature available discusses the use of either the delta / ASM
 	  API with setsockopt(2)/getsockopt(2), or the full-state / ASM API
 	  using setsourcefilter(3)/getsourcefilter(3). For more information
 	  please refer to RFC 3768, 'Socket Interface Extensions for
 	  Multicast Source Filters'.
 
 	* Applications which use the published RFC 3678 APIs should be fine.
 
 	For systems administrators:
 
 	* The mtest(8) utility has been refactored to support IPv6, in
 	  addition to IPv4. Interface addresses are no longer accepted
 	  as arguments, their names must be used instead. The utility
 	  will map the interface name to its first IPv4 address as
 	  returned by getifaddrs(3).
 
 	* The ifmcstat(8) utility has also been updated to print the MLDv2
 	  endpoint state and source filter lists via sysctl(3).
 
 	* The net.inet6.ip6.mcast.loop sysctl may be tuned to 0 to disable
 	  loopback of IPv6 multicast datagrams by default; it defaults to 1
 	  to preserve the existing behaviour. Disabling multicast loopback is
 	  recommended for optimal system performance.
 
 	* The IPv6 MROUTING code has been changed to examine this sysctl
 	  instead of attempting to perform a group lookup before looping
 	  back forwarded datagrams.
 
 	Bump __FreeBSD_version to 800084.
 
 20090422:
 	Implement low-level Bluetooth HCI API.
 	Bump __FreeBSD_version to 800083.
 
 20090419:
 	The layout of struct malloc_type, used by modules to register new
 	memory allocation types, has changed.  Most modules will need to
 	be rebuilt or panics may be experienced.
 	Bump __FreeBSD_version to 800081.
 
 20090415:
 	Anticipate overflowing inp_flags - add inp_flags2.
 	This changes most offsets in inpcb, so checking v4 connection
 	state will require a world rebuild.
 	Bump __FreeBSD_version to 800080.
 
 20090415:
 	Add an llentry to struct route and struct route_in6. Modules
 	embedding a struct route will need to be recompiled.
 	Bump __FreeBSD_version to 800079.
 
 20090414:
 	The size of rt_metrics_lite and by extension rtentry has changed.
 	Networking administration apps will need to be recompiled.
 	The route command now supports show as an alias for get, weighting
 	of routes, sticky and nostick flags to alter the behavior of stateful
 	load balancing.
 	Bump __FreeBSD_version to 800078.
 
 20090408:
 	Do not use Giant for kbdmux(4) locking. This is wrong and
 	apparently causing more problems than it solves. This will
 	re-open the issue where interrupt handlers may race with
 	kbdmux(4) in polling mode. Typical symptoms include (but
 	not limited to) duplicated and/or missing characters when
 	low level console functions (such as gets) are used while
 	interrupts are enabled (for example geli password prompt,
 	mountroot prompt etc.). Disabling kbdmux(4) may help.
 
 20090407:
 	The size of structs vnet_net, vnet_inet and vnet_ipfw has changed;
 	kernel modules referencing any of the above need to be recompiled.
 	Bump __FreeBSD_version to 800075.
 
 20090320:
 	GEOM_PART has become the default partition slicer for storage devices,
 	replacing GEOM_MBR, GEOM_BSD, GEOM_PC98 and GEOM_GPT slicers. It
 	introduces some changes:
 
 	MSDOS/EBR: the devices created from MSDOS extended partition entries
 	(EBR) can be named differently than with GEOM_MBR and are now symlinks
 	to devices with offset-based names. fstabs may need to be modified.
 
 	BSD: the "geometry does not match label" warning is harmless in most
 	cases but it points to problems in file system misalignment with
 	disk geometry. The "c" partition is now implicit, covers the whole
 	top-level drive and cannot be (mis)used by users.
 
 	General: Kernel dumps are now not allowed to be written to devices
 	whose partition types indicate they are meant to be used for file
 	systems (or, in case of MSDOS partitions, as something else than
 	the "386BSD" type).
 
 	Most of these changes date approximately from 200812.
 
 20090319:
 	The uscanner(4) driver has been removed from the kernel. This follows
 	Linux removing theirs in 2.6 and making libusb the default interface
 	(supported by sane).
 
 20090319:
 	The multicast forwarding code has been cleaned up. netstat(1)
 	only relies on KVM now for printing bandwidth upcall meters.
 	The IPv4 and IPv6 modules are split into ip_mroute_mod and
 	ip6_mroute_mod respectively. The config(5) options for statically
 	compiling this code remain the same, i.e. 'options MROUTING'.
 
 20090315:
 	Support for the IFF_NEEDSGIANT network interface flag has been
 	removed, which means that non-MPSAFE network device drivers are no
 	longer supported.  In particular, if_ar, if_sr, and network device
 	drivers from the old (legacy) USB stack can no longer be built or
 	used.
 
 20090313:
 	POSIX.1 Native Language Support (NLS) has been enabled in libc and
 	a bunch of new language catalog files have also been added.
 	This means that some common libc messages are now localized and
 	they depend on the LC_MESSAGES environmental variable.
 
 20090313:
 	The k8temp(4) driver has been renamed to amdtemp(4) since
 	support for K10 and K11 CPU families was added.
 
 20090309:
 	IGMPv3 and Source-Specific Multicast (SSM) have been merged
 	to the IPv4 stack. VIMAGE hooks are in but not yet used.
 
 	For kernel developers, the most important changes are that the
 	ip_output() and ip_input() paths no longer take the IN_MULTI_LOCK(),
 	and this lock has been downgraded to a non-recursive mutex.
 
 	Transport protocols (UDP, Raw IP) are now responsible for filtering
 	inbound multicast traffic according to group membership and source
 	filters. The imo_multicast_filter() KPI exists for this purpose.
 	Transports which do not use multicast (SCTP, TCP) already reject
 	multicast by default. Forwarding and receive performance may improve
 	as a mutex acquisition is no longer needed in the ip_input()
 	low-level input path.  in_addmulti() and in_delmulti() are shimmed
 	to new KPIs which exist to support SSM in-kernel.
 
 	For application developers, it is recommended that loopback of
 	multicast datagrams be disabled for best performance, as this
 	will still cause the lock to be taken for each looped-back
 	datagram transmission. The net.inet.ip.mcast.loop sysctl may
 	be tuned to 0 to disable loopback by default; it defaults to 1
 	to preserve the existing behaviour.
 
 	For systems administrators, to obtain best performance with
 	multicast reception and multiple groups, it is always recommended
 	that a card with a suitably precise hash filter is used. Hash
 	collisions will still result in the lock being taken within the
 	transport protocol input path to check group membership.
 
 	If deploying FreeBSD in an environment with IGMP snooping switches,
 	it is recommended that the net.inet.igmp.sendlocal sysctl remain
 	enabled; this forces 224.0.0.0/24 group membership to be announced
 	via IGMP.
 
 	The size of 'struct igmpstat' has changed; netstat needs to be
 	recompiled to reflect this.
 	Bump __FreeBSD_version to 800070.
 
 20090309:
 	libusb20.so.1 is now installed as libusb.so.1 and the ports system
 	updated to use it. This requires a buildworld/installworld in order to
 	update the library and dependencies (usbconfig, etc). Its advisable to
 	rebuild all ports which uses libusb. More specific directions are given
 	in the ports collection UPDATING file. Any /etc/libmap.conf entries for
 	libusb are no longer required and can be removed.
 
 20090302:
 	A workaround is committed to allow the creation of System V shared
 	memory segment of size > 2 GB on the 64-bit architectures.
 	Due to a limitation of the existing ABI, the shm_segsz member
 	of the struct shmid_ds, returned by shmctl(IPC_STAT) call is
 	wrong for large segments. Note that limits must be explicitly
 	raised to allow such segments to be created.
 
 20090301:
 	The layout of struct ifnet has changed, requiring a rebuild of all
 	network device driver modules.
 
 20090227:
 	The /dev handling for the new USB stack has changed, a
 	buildworld/installworld is required for libusb20.
 
 20090223:
 	The new USB2 stack has now been permanently moved in and all kernel and
 	module names reverted to their previous values (eg, usb, ehci, ohci,
 	ums, ...).  The old usb stack can be compiled in by prefixing the name
 	with the letter 'o', the old usb modules have been removed.
 	Updating entry 20090216 for xorg and 20090215 for libmap may still
 	apply.
 
 20090217:
 	The rc.conf(5) option if_up_delay has been renamed to
 	defaultroute_delay to better reflect its purpose. If you have
 	customized this setting in /etc/rc.conf you need to update it to
 	use the new name.
 
 20090216:
 	xorg 7.4 wants to configure its input devices via hald which does not
 	yet work with USB2. If the keyboard/mouse does not work in xorg then
 	add
 		Option "AllowEmptyInput" "off"
 	to your ServerLayout section.  This will cause X to use the configured
 	kbd and mouse sections from your xorg.conf.
 
 20090215:
 	The GENERIC kernels for all architectures now default to the new USB2
 	stack. No kernel config options or code have been removed so if a
 	problem arises please report it and optionally revert to the old USB
 	stack. If you are loading USB kernel modules or have a custom kernel
 	that includes GENERIC then ensure that usb names are also changed over,
 	eg uftdi -> usb2_serial_ftdi.
 
 	Older programs linked against the ports libusb 0.1 need to be
 	redirected to the new stack's libusb20.  /etc/libmap.conf can
 	be used for this:
 		# Map old usb library to new one for usb2 stack
 		libusb-0.1.so.8	libusb20.so.1
 
 20090209:
 	All USB ethernet devices now attach as interfaces under the name ueN
 	(eg. ue0). This is to provide a predictable name as vendors often
 	change usb chipsets in a product without notice.
 
 20090203:
 	The ichsmb(4) driver has been changed to require SMBus slave
 	addresses be left-justified (xxxxxxx0b) rather than right-justified.
 	All of the other SMBus controller drivers require left-justified
 	slave addresses, so this change makes all the drivers provide the
 	same interface.
 
 20090201:
 	INET6 statistics (struct ip6stat) was updated.
 	netstat(1) needs to be recompiled.
 
 20090119:
 	NTFS has been removed from GENERIC kernel on amd64 to match
 	GENERIC on i386. Should not cause any issues since mount_ntfs(8)
 	will load ntfs.ko module automatically when NTFS support is
 	actually needed, unless ntfs.ko is not installed or security
 	level prohibits loading kernel modules. If either is the case,
 	"options NTFS" has to be added into kernel config.
 
 20090115:
 	TCP Appropriate Byte Counting (RFC 3465) support added to kernel.
 	New field in struct tcpcb breaks ABI, so bump __FreeBSD_version to
 	800061. User space tools that rely on the size of struct tcpcb in
 	tcp_var.h (e.g. sockstat) need to be recompiled.
 
 20081225:
 	ng_tty(4) module updated to match the new TTY subsystem.
 	Due to API change, user-level applications must be updated.
 	New API support added to mpd5 CVS and expected to be present
 	in next mpd5.3 release.
 
 20081219:
 	With __FreeBSD_version 800060 the makefs tool is part of
 	the base system (it was a port).
 
 20081216:
 	The afdata and ifnet locks have been changed from mutexes to
 	rwlocks, network modules will need to be re-compiled.
 
 20081214:
 	__FreeBSD_version 800059 incorporates the new arp-v2 rewrite.
 	RTF_CLONING, RTF_LLINFO and RTF_WASCLONED flags are eliminated.
 	The new code reduced struct rtentry{} by 16 bytes on 32-bit
 	architecture and 40 bytes on 64-bit architecture. The userland
 	applications "arp" and "ndp" have been updated accordingly.
 	The output from "netstat -r" shows only routing entries and
 	none of the L2 information.
 
 20081130:
 	__FreeBSD_version 800057 marks the switchover from the
 	binary ath hal to source code. Users must add the line:
 
 	options	AH_SUPPORT_AR5416
 
 	to their kernel config files when specifying:
 
 	device	ath_hal
 
 	The ath_hal module no longer exists; the code is now compiled
 	together with the driver in the ath module.  It is now
 	possible to tailor chip support (i.e. reduce the set of chips
 	and thereby the code size); consult ath_hal(4) for details.
 
 20081121:
 	__FreeBSD_version 800054 adds memory barriers to
 	, new interfaces to ifnet to facilitate
 	multiple hardware transmit queues for cards that support
 	them, and a lock-less ring-buffer implementation to
 	enable drivers to more efficiently manage queueing of
 	packets.
 
 20081117:
 	A new version of ZFS (version 13) has been merged to -HEAD.
 	This version has zpool attribute "listsnapshots" off by
 	default, which means "zfs list" does not show snapshots,
 	and is the same as Solaris behavior.
 
 20081028:
 	dummynet(4) ABI has changed. ipfw(8) needs to be recompiled.
 
 20081009:
 	The uhci, ohci, ehci and slhci USB Host controller drivers have
 	been put into separate modules. If you load the usb module
 	separately through loader.conf you will need to load the
 	appropriate *hci module as well. E.g. for a UHCI-based USB 2.0
 	controller add the following to loader.conf:
 
 		uhci_load="YES"
 		ehci_load="YES"
 
 20081009:
 	The ABI used by the PMC toolset has changed.  Please keep
 	userland (libpmc(3)) and the kernel module (hwpmc(4)) in
 	sync.
 
 20081009:
 	atapci kernel module now includes only generic PCI ATA
 	driver. AHCI driver moved to ataahci kernel module.
 	All vendor-specific code moved into separate kernel modules:
 	ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek,
 	atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron,
 	atamarvell, atamicron, atanational, atanetcell, atanvidia,
 	atapromise, ataserverworks, atasiliconimage, atasis, atavia
 
 20080820:
 	The TTY subsystem of the kernel has been replaced by a new
 	implementation, which provides better scalability and an
 	improved driver model. Most common drivers have been migrated to
 	the new TTY subsystem, while others have not. The following
 	drivers have not yet been ported to the new TTY layer:
 
 	PCI/ISA:
 		cy, digi, rc, rp, sio
 
 	USB:
 		ubser, ucycom
 
 	Line disciplines:
 		ng_h4, ng_tty, ppp, sl, snp
 
 	Adding these drivers to your kernel configuration file shall
 	cause compilation to fail.
 
 20080818:
 	ntpd has been upgraded to 4.2.4p5.
 
 20080801:
 	OpenSSH has been upgraded to 5.1p1.
 
 	For many years, FreeBSD's version of OpenSSH preferred DSA
 	over RSA for host and user authentication keys.  With this
 	upgrade, we've switched to the vendor's default of RSA over
 	DSA.  This may cause upgraded clients to warn about unknown
 	host keys even for previously known hosts.  Users should
 	follow the usual procedure for verifying host keys before
 	accepting the RSA key.
 
 	This can be circumvented by setting the "HostKeyAlgorithms"
 	option to "ssh-dss,ssh-rsa" in ~/.ssh/config or on the ssh
 	command line.
 
 	Please note that the sequence of keys offered for
 	authentication has been changed as well.  You may want to
 	specify IdentityFile in a different order to revert this
 	behavior.
 
 20080713:
 	The sio(4) driver has been removed from the i386 and amd64
 	kernel configuration files. This means uart(4) is now the
 	default serial port driver on those platforms as well.
 
 	To prevent collisions with the sio(4) driver, the uart(4) driver
 	uses different names for its device nodes. This means the
 	onboard serial port will now most likely be called "ttyu0"
 	instead of "ttyd0". You may need to reconfigure applications to
 	use the new device names.
 
 	When using the serial port as a boot console, be sure to update
 	/boot/device.hints and /etc/ttys before booting the new kernel.
 	If you forget to do so, you can still manually specify the hints
 	at the loader prompt:
 
 		set hint.uart.0.at="isa"
 		set hint.uart.0.port="0x3F8"
 		set hint.uart.0.flags="0x10"
 		set hint.uart.0.irq="4"
 		boot -s
 
 20080609:
 	The gpt(8) utility has been removed. Use gpart(8) to partition
 	disks instead.
 
 20080603:
 	The version that Linuxulator emulates was changed from 2.4.2
 	to 2.6.16. If you experience any problems with Linux binaries
 	please try to set sysctl compat.linux.osrelease to 2.4.2 and
 	if it fixes the problem contact emulation mailing list.
 
 20080525:
 	ISDN4BSD (I4B) was removed from the src tree. You may need to
 	update a your kernel configuration and remove relevant entries.
 
 20080509:
 	I have checked in code to support multiple routing tables.
 	See the man pages setfib(1) and setfib(2).
 	This is a hopefully backwards compatible version,
 	but to make use of it you need to compile your kernel
 	with options ROUTETABLES=2 (or more up to 16).
 
 20080420:
 	The 802.11 wireless support was redone to enable multi-bss
 	operation on devices that are capable.  The underlying device
 	is no longer used directly but instead wlanX devices are
 	cloned with ifconfig.  This requires changes to rc.conf files.
 	For example, change:
 		ifconfig_ath0="WPA DHCP"
 	to
 		wlans_ath0=wlan0
 		ifconfig_wlan0="WPA DHCP"
 	see rc.conf(5) for more details.  In addition, mergemaster of
 	/etc/rc.d is highly recommended.  Simultaneous update of userland
 	and kernel wouldn't hurt either.
 
 	As part of the multi-bss changes the wlan_scan_ap and wlan_scan_sta
 	modules were merged into the base wlan module.  All references
 	to these modules (e.g. in kernel config files) must be removed.
 
 20080408:
 	psm(4) has gained write(2) support in native operation level.
 	Arbitrary commands can be written to /dev/psm%d and status can
 	be read back from it.  Therefore, an application is responsible
 	for status validation and error recovery.  It is a no-op in
 	other operation levels.
 
 20080312:
 	Support for KSE threading has been removed from the kernel.  To
 	run legacy applications linked against KSE libmap.conf may
 	be used.  The following libmap.conf may be used to ensure
 	compatibility with any prior release:
 
 	libpthread.so.1 libthr.so.1
 	libpthread.so.2 libthr.so.2
 	libkse.so.3 libthr.so.3
 
 20080301:
 	The layout of struct vmspace has changed. This affects libkvm
 	and any executables that link against libkvm and use the
 	kvm_getprocs() function. In particular, but not exclusively,
 	it affects ps(1), fstat(1), pkill(1), systat(1), top(1) and w(1).
 	The effects are minimal, but it's advisable to upgrade world
 	nonetheless.
 
 20080229:
 	The latest em driver no longer has support in it for the
 	82575 adapter, this is now moved to the igb driver. The
 	split was done to make new features that are incompatible
 	with older hardware easier to do.
 
 20080220:
 	The new geom_lvm(4) geom class has been renamed to geom_linux_lvm(4),
 	likewise the kernel option is now GEOM_LINUX_LVM.
 
 20080211:
 	The default NFS mount mode has changed from UDP to TCP for
 	increased reliability.  If you rely on (insecurely) NFS
 	mounting across a firewall you may need to update your
 	firewall rules.
 
 20080208:
 	Belatedly note the addition of m_collapse for compacting
 	mbuf chains.
 
 20080126:
 	The fts(3) structures have been changed to use adequate
 	integer types for their members and so to be able to cope
 	with huge file trees.  The old fts(3) ABI is preserved
 	through symbol versioning in libc, so third-party binaries
 	using fts(3) should still work, although they will not take
 	advantage of the extended types.  At the same time, some
 	third-party software might fail to build after this change
 	due to unportable assumptions made in its source code about
 	fts(3) structure members.  Such software should be fixed
 	by its vendor or, in the worst case, in the ports tree.
 	FreeBSD_version 800015 marks this change for the unlikely
 	case that a portable fix is impossible.
 
 20080123:
 	To upgrade to -current after this date, you must be running
 	FreeBSD not older than 6.0-RELEASE.  Upgrading to -current
 	from 5.x now requires a stop over at RELENG_6 or RELENG_7 systems.
 
 20071128:
 	The ADAPTIVE_GIANT kernel option has been retired because its
 	functionality is the default now.
 
 20071118:
 	The AT keyboard emulation of sunkbd(4) has been turned on
 	by default. In order to make the special symbols of the Sun
 	keyboards driven by sunkbd(4) work under X these now have
 	to be configured the same way as Sun USB keyboards driven
 	by ukbd(4) (which also does AT keyboard emulation), f.e.:
 
 	Option	"XkbLayout" "us"
 	Option	"XkbRules" "xorg"
 	Option	"XkbSymbols" "pc(pc105)+sun_vndr/usb(sun_usb)+us"
 
 20071024:
 	It has been decided that it is desirable to provide ABI
 	backwards compatibility to the FreeBSD 4/5/6 versions of the
 	PCIOCGETCONF, PCIOCREAD and PCIOCWRITE IOCTLs, which was
 	broken with the introduction of PCI domain support (see the
 	20070930 entry). Unfortunately, this required the ABI of
 	PCIOCGETCONF to be broken again in order to be able to
 	provide backwards compatibility to the old version of that
 	IOCTL. Thus consumers of PCIOCGETCONF have to be recompiled
 	again. As for prominent ports this affects neither pciutils
 	nor xorg-server this time, the hal port needs to be rebuilt
 	however.
 
 20071020:
 	The misnamed kthread_create() and friends have been renamed
 	to kproc_create() etc. Many of the callers already
 	used kproc_start()..
 	I will return kthread_create() and friends in a while
 	with implementations that actually create threads, not procs.
 	Renaming corresponds with version 800002.
 
 20071010:
 	RELENG_7 branched.
 
 20071009:
 	Setting WITHOUT_LIBPTHREAD now means WITHOUT_LIBKSE and
 	WITHOUT_LIBTHR are set.
 
 20070930:
 	The PCI code has been made aware of PCI domains. This means that
 	the location strings as used by pciconf(8) etc are now in the
 	following format: pci::[:]. It
 	also means that consumers of  potentially need to
 	be recompiled; this includes the hal and xorg-server ports.
 
 20070928:
 	The caching daemon (cached) was renamed to nscd. nscd.conf
 	configuration file should be used instead of cached.conf and
 	nscd_enable, nscd_pidfile and nscd_flags options should be used
 	instead of cached_enable, cached_pidfile and cached_flags in
 	rc.conf.
 
 20070921:
 	The getfacl(1) utility now prints owning user and group name
 	instead of owning uid and gid in the three line comment header.
 	This is the same behavior as getfacl(1) on Solaris and Linux.
 
 20070704:
 	The new IPsec code is now compiled in using the IPSEC option.  The
 	IPSEC option now requires "device crypto" be defined in your kernel
 	configuration.  The FAST_IPSEC kernel option is now deprecated.
 
 20070702:
 	The packet filter (pf) code has been updated to OpenBSD 4.1 Please
 	note the changed syntax - keep state is now on by default.  Also
 	note the fact that ftp-proxy(8) has been changed from bottom up and
 	has been moved from libexec to usr/sbin.  Changes in the ALTQ
 	handling also affect users of IPFW's ALTQ capabilities.
 
 20070701:
 	Remove KAME IPsec in favor of FAST_IPSEC, which is now the
 	only IPsec supported by FreeBSD.  The new IPsec stack
 	supports both IPv4 and IPv6. The kernel option will change
 	after the code changes have settled in.  For now the kernel
 	option IPSEC is deprecated and FAST_IPSEC is the only option, that
 	will change after some settling time.
 
 20070701:
 	The wicontrol(8) utility has been removed from the base system. wi(4)
 	cards should be configured using ifconfig(8), see the man page for more
 	information.
 
 20070612:
 	The i386/amd64 GENERIC kernel now defaults to the nfe(4) driver
 	instead of the nve(4) driver. Please update your configuration
 	accordingly.
 
 20070612:
 	By default, /etc/rc.d/sendmail no longer rebuilds the aliases
 	database if it is missing or older than the aliases file.  If
 	desired, set the new rc.conf option sendmail_rebuild_aliases
 	to "YES" to restore that functionality.
 
 20070612:
 	The IPv4 multicast socket code has been considerably modified, and
 	moved to the file sys/netinet/in_mcast.c. Initial support for the
 	RFC 3678 Source-Specific Multicast Socket API has been added to
 	the IPv4 network stack.
 
 	Strict multicast and broadcast reception is now the default for
 	UDP/IPv4 sockets; the net.inet.udp.strict_mcast_mship sysctl variable
 	has now been removed.
 
 	The RFC 1724 hack for interface selection has been removed; the use
 	of the Linux-derived ip_mreqn structure with IP_MULTICAST_IF has
 	been added to replace it. Consumers such as routed will soon be
 	updated to reflect this.
 
 	These changes affect users who are running routed(8) or rdisc(8)
 	from the FreeBSD base system on point-to-point or unnumbered
 	interfaces.
 
 20070610:
 	The net80211 layer has changed significantly and all wireless
 	drivers that depend on it need to be recompiled.  Further these
 	changes require that any program that interacts with the wireless
 	support in the kernel be recompiled; this includes: ifconfig,
 	wpa_supplicant, hostapd, and wlanstats.  Users must also, for
 	the moment, kldload the wlan_scan_sta and/or wlan_scan_ap modules
 	if they use modules for wireless support.  These modules implement
 	scanning support for station and ap modes, respectively.  Failure
 	to load the appropriate module before marking a wireless interface
 	up will result in a message to the console and the device not
 	operating properly.
 
 20070610:
 	The pam_nologin(8) module ceases to provide an authentication
 	function and starts providing an account management function.
 	Consequent changes to /etc/pam.d should be brought in using
 	mergemaster(8).  Third-party files in /usr/local/etc/pam.d may
 	need manual editing as follows.  Locate this line (or similar):
 
 		auth	required	pam_nologin.so	no_warn
 
 	and change it according to this example:
 
 		account	required	pam_nologin.so	no_warn
 
 	That is, the first word needs to be changed from "auth" to
 	"account".  The new line can be moved to the account section
 	within the file for clarity.  Not updating pam.conf(5) files
 	will result in nologin(5) ignored by the respective services.
 
 20070529:
 	The ether_ioctl() function has been synchronized with ioctl(2)
 	and ifnet.if_ioctl.  Due to that, the size of one of its arguments
 	has changed on 64-bit architectures.  All kernel modules using
 	ether_ioctl() need to be rebuilt on such architectures.
 
 20070516:
 	Improved INCLUDE_CONFIG_FILE support has been introduced to the
 	config(8) utility. In order to take advantage of this new
 	functionality, you are expected to recompile and install
 	src/usr.sbin/config. If you don't rebuild config(8), and your
 	kernel configuration depends on INCLUDE_CONFIG_FILE, the kernel
 	build will be broken because of a missing "kernconfstring"
 	symbol.
 
 20070513:
 	Symbol versioning is enabled by default.  To disable it, use
 	option WITHOUT_SYMVER.  It is not advisable to attempt to
 	disable symbol versioning once it is enabled; your installworld
 	will break because a symbol version-less libc will get installed
 	before the install tools.  As a result, the old install tools,
 	which previously had symbol dependencies to FBSD_1.0, will fail
 	because the freshly installed libc will not have them.
 
 	The default threading library (providing "libpthread") has been
 	changed to libthr.  If you wish to have libkse as your default,
 	use option DEFAULT_THREAD_LIB=libkse for the buildworld.
 
 20070423:
 	The ABI breakage in sendmail(8)'s libmilter has been repaired
 	so it is no longer necessary to recompile mail filters (aka,
 	milters).  If you recompiled mail filters after the 20070408
 	note, it is not necessary to recompile them again.
 
 20070417:
 	The new trunk(4) driver has been renamed to lagg(4) as it better
 	reflects its purpose. ifconfig will need to be recompiled.
 
 20070408:
 	sendmail(8) has been updated to version 8.14.1.  Mail filters
 	(aka, milters) compiled against the libmilter included in the
 	base operating system should be recompiled.
 
 20070302:
 	Firmwares for ipw(4) and iwi(4) are now included in the base tree.
 	In order to use them one must agree to the respective LICENSE in
 	share/doc/legal and define legal.intel_.license_ack=1 via
 	loader.conf(5) or kenv(1).  Make sure to deinstall the now
 	deprecated modules from the respective firmware ports.
 
 20070228:
 	The name resolution/mapping functions addr2ascii(3) and ascii2addr(3)
 	were removed from FreeBSD's libc. These originally came from INRIA
 	IPv6. Nothing in FreeBSD ever used them. They may be regarded as
 	deprecated in previous releases.
 	The AF_LINK support for getnameinfo(3) was merged from NetBSD to
 	replace it as a more portable (and re-entrant) API.
 
 20070224:
 	To support interrupt filtering a modification to the newbus API
 	has occurred, ABI was broken and __FreeBSD_version was bumped
 	to 700031. Please make sure that your kernel and modules are in
 	sync. For more info:
 	http://docs.freebsd.org/cgi/mid.cgi?20070221233124.GA13941
 
 20070224:
 	The IPv6 multicast forwarding code may now be loaded into GENERIC
 	kernels by loading the ip_mroute.ko module. This is built into the
 	module unless WITHOUT_INET6 or WITHOUT_INET6_SUPPORT options are
 	set; see src.conf(5) for more information.
 
 20070214:
 	The output of netstat -r has changed. Without -n, we now only
 	print a "network name" without the prefix length if the network
 	address and mask exactly match a Class A/B/C network, and an entry
 	exists in the nsswitch "networks" map.
 	With -n, we print the full unabbreviated CIDR network prefix in
 	the form "a.b.c.d/p". 0.0.0.0/0 is always printed as "default".
 	This change is in preparation for changes such as equal-cost
 	multipath, and to more generally assist operational deployment
 	of FreeBSD as a modern IPv4 router.
 
 20070210:
 	PIM has been turned on by default in the IPv4 multicast
 	routing code. The kernel option 'PIM' has now been removed.
 	PIM is now built by default if option 'MROUTING' is specified.
 	It may now be loaded into GENERIC kernels by loading the
 	ip_mroute.ko module.
 
 20070207:
 	Support for IPIP tunnels (VIFF_TUNNEL) in IPv4 multicast routing
 	has been removed. Its functionality may be achieved by explicitly
 	configuring gif(4) interfaces and using the 'phyint' keyword in
 	mrouted.conf.
 	XORP does not support source-routed IPv4 multicast tunnels nor the
 	integrated IPIP tunneling, therefore it is not affected by this
 	change. The __FreeBSD_version macro has been bumped to 700030.
 
 20061221:
 	Support for PCI Message Signalled Interrupts has been
 	re-enabled in the bge driver, only for those chips which are
 	believed to support it properly.  If there are any problems,
 	MSI can be disabled completely by setting the
 	'hw.pci.enable_msi' and 'hw.pci.enable_msix' tunables to 0
 	in the loader.
 
 20061214:
 	Support for PCI Message Signalled Interrupts has been
 	disabled again in the bge driver.  Many revisions of the
 	hardware fail to support it properly.  Support can be
 	re-enabled by removing the #define of BGE_DISABLE_MSI in
 	"src/sys/dev/bge/if_bge.c".
 
 20061214:
 	Support for PCI Message Signalled Interrupts has been added
 	to the bge driver.  If there are any problems, MSI can be
 	disabled completely by setting the 'hw.pci.enable_msi' and
 	'hw.pci.enable_msix' tunables to 0 in the loader.
 
 20061205:
 	The removal of several facets of the experimental Threading
 	system from the kernel means that the proc and thread structures
 	have changed quite a bit. I suggest all kernel modules that might
 	reference these structures be recompiled.. Especially the
 	linux module.
 
 20061126:
 	Sound infrastructure has been updated with various fixes and
 	improvements. Most of the changes are pretty much transparent,
 	with exceptions of followings:
 	1) All sound driver specific sysctls (hw.snd.pcm%d.*) have been
 	   moved to their own dev sysctl nodes, for example:
 		hw.snd.pcm0.vchans -> dev.pcm.0.vchans
 	2) /dev/dspr%d.%d has been deprecated. Each channel now has its
 	   own chardev in the form of "dsp%d.%d", where 
 	   is p = playback, r = record and v = virtual, respectively. Users
 	   are encouraged to use these devs instead of (old) "/dev/dsp%d.%d".
 	   This does not affect those who are using "/dev/dsp".
 
 20061122:
 	geom(4)'s gmirror(8) class metadata structure has been
 	rev'd from v3 to v4. If you update across this point and
 	your metadata is converted for you, you will not be easily
 	able to downgrade since the /boot/kernel.old/geom_mirror.ko
 	kernel module will be unable to read the v4 metadata.  You
 	can resolve this by doing from the loader(8) prompt:
 
 		set vfs.root.mountfrom="ufs:/dev/XXX"
 
 	where XXX is the root slice of one of the disks that composed
 	the mirror (i.e.: /dev/ad0s1a). You can then rebuild
 	the array the same way you built it originally.
 
 20061122:
 	The following binaries have been disconnected from the build:
 	mount_devfs, mount_ext2fs, mount_fdescfs, mount_procfs, mount_linprocfs,
 	and mount_std.  The functionality of these programs has been
 	moved into the mount program.  For example, to mount a devfs
 	filesystem, instead of using mount_devfs, use: "mount -t devfs".
 	This does not affect entries in /etc/fstab, since entries in
 	/etc/fstab are always processed with "mount -t fstype".
 
 20061113:
 	Support for PCI Message Signalled Interrupts on i386 and amd64
 	has been added to the kernel and various drivers will soon be
 	updated to use MSI when it is available.  If there are any problems,
 	MSI can be disabled completely by setting the 'hw.pci.enable_msi'
 	and 'hw.pci.enable_msix' tunables to 0 in the loader.
 
 20061110:
 	The MUTEX_PROFILING option has been renamed to LOCK_PROFILING.
 	The lockmgr object layout has been changed as a result of having
 	a lock_object embedded in it. As a consequence all file system
 	kernel modules must be re-compiled. The mutex profiling man page
 	has not yet been updated to reflect this change.
 
 20061026:
 	KSE in the kernel has now been made optional and turned on by
 	default. Use 'nooption KSE' in your kernel config to turn it
 	off. All kernel modules *must* be recompiled after this change.
 	There-after, modules from a KSE kernel should be compatible with
 	modules from a NOKSE kernel due to the temporary padding fields
 	added to 'struct proc'.
 
 20060929:
 	mrouted and its utilities have been removed from the base system.
 
 20060927:
 	Some ioctl(2) command codes have changed.  Full backward ABI
 	compatibility is provided if the "options COMPAT_FREEBSD6" is
 	present in the kernel configuration file.  Make sure to add
 	this option to your kernel config file, or recompile X.Org
 	and the rest of ports; otherwise they may refuse to work.
 
 20060924:
 	tcpslice has been removed from the base system.
 
 20060913:
 	The sizes of struct tcpcb (and struct xtcpcb) have changed due to
 	the rewrite of TCP syncookies.  Tools like netstat, sockstat, and
 	systat needs to be rebuilt.
 
 20060903:
 	libpcap updated to v0.9.4 and tcpdump to v3.9.4
 
 20060816:
 	The IPFIREWALL_FORWARD_EXTENDED option is gone and the behaviour
 	for IPFIREWALL_FORWARD is now as it was before when it was first
 	committed and for years after. The behaviour is now ON.
 
 20060725:
 	enigma(1)/crypt(1) utility has been changed on 64 bit architectures.
 	Now it can decrypt files created from different architectures.
 	Unfortunately, it is no longer able to decrypt a cipher text
 	generated with an older version on 64 bit architectures.
 	If you have such a file, you need old utility to decrypt it.
 
 20060709:
 	The interface version of the i4b kernel part has changed. So
 	after updating the kernel sources and compiling a new kernel,
 	the i4b user space tools in "/usr/src/usr.sbin/i4b" must also
 	be rebuilt, and vice versa.
 
 20060627:
 	The XBOX kernel now defaults to the nfe(4) driver instead of
 	the nve(4) driver. Please update your configuration
 	accordingly.
 
 20060514:
 	The i386-only lnc(4) driver for the AMD Am7900 LANCE and Am79C9xx
 	PCnet family of NICs has been removed. The new le(4) driver serves
 	as an equivalent but cross-platform replacement with the pcn(4)
 	driver still providing performance-optimized support for the subset
 	of AMD Am79C971 PCnet-FAST and greater chips as before.
 
 20060511:
 	The machdep.* sysctls and the adjkerntz utility have been
 	modified a bit.  The new adjkerntz utility uses the new
 	sysctl names and sysctlbyname() calls, so it may be impossible
 	to run an old /sbin/adjkerntz utility in single-user mode
 	with a new kernel.  Replace the `adjkerntz -i' step before
 	`make installworld' with:
 
 	    /usr/obj/usr/src/sbin/adjkerntz/adjkerntz -i
 
 	and proceed as usual with the rest of the installworld-stage
 	steps.  Otherwise, you risk installing binaries with their
 	timestamp set several hours in the future, especially if
 	you are running with local time set to GMT+X hours.
 
 20060412:
 	The ip6fw utility has been removed.  The behavior provided by
 	ip6fw has been in ipfw2 for a good while and the rc.d scripts
 	have been updated to deal with it.  There are some rules that
 	might not migrate cleanly.  Use rc.firewall6 as a template to
 	rewrite rules.
 
 20060428:
 	The puc(4) driver has been overhauled. The ebus(4) and sbus(4)
 	attachments have been removed. Make sure to configure scc(4)
 	on sparc64. Note also that by default puc(4) will use uart(4)
 	and not sio(4) for serial ports because interrupt handling has
 	been optimized for multi-port serial cards and only uart(4)
 	implements the interface to support it.
 
 20060330:
 	The scc(4) driver replaces puc(4) for Serial Communications
 	Controllers (SCCs) like the Siemens SAB82532 and the Zilog
 	Z8530. On sparc64, it is advised to add scc(4) to the kernel
 	configuration to make sure that the serial ports remain
 	functional.
 
 20060317:
 	Most world/kernel related NO_* build options changed names.
 	New knobs have common prefixes WITHOUT_*/WITH_* (modelled
 	after FreeBSD ports) and should be set in /etc/src.conf
 	(the src.conf(5) manpage is provided).  Full backwards
 	compatibility is maintained for the time being though it's
 	highly recommended to start moving old options out of the
 	system-wide /etc/make.conf file into the new /etc/src.conf
 	while also properly renaming them.  More conversions will
 	likely follow.  Posting to current@:
 
 	http://lists.freebsd.org/pipermail/freebsd-current/2006-March/061725.html
 
 20060305:
 	The NETSMBCRYPTO kernel option has been retired because its
 	functionality is always included in NETSMB and smbfs.ko now.
 
 20060303:
 	The TDFX_LINUX kernel option was retired and replaced by the
 	tdfx_linux device.  The latter can be loaded as the 3dfx_linux.ko
 	kernel module.  Loading it alone should suffice to get 3dfx support
 	for Linux apps because it will pull in 3dfx.ko and linux.ko through
 	its dependencies.
 
 20060204:
 	The 'audit' group was added to support the new auditing functionality
 	in the base system.  Be sure to follow the directions for updating,
 	including the requirement to run mergemaster -p.
 
 20060201:
 	The kernel ABI to file system modules was changed on i386.
 	Please make sure that your kernel and modules are in sync.
 
 20060118:
 	This actually occured some time ago, but installing the kernel
 	now also installs a bunch of symbol files for the kernel modules.
 	This increases the size of /boot/kernel to about 67Mbytes. You
 	will need twice this if you will eventually back this up to kernel.old
 	on your next install.
 	If you have a shortage of room in your root partition, you should add
 	-DINSTALL_NODEBUG to your make arguments or add INSTALL_NODEBUG="yes"
 	to your /etc/make.conf.
 
 20060113:
 	libc's malloc implementation has been replaced.  This change has the
 	potential to uncover application bugs that previously went unnoticed.
 	See the malloc(3) manual page for more details.
 
 20060112:
 	The generic netgraph(4) cookie has been changed. If you upgrade
 	kernel passing this point, you also need to upgrade userland
 	and netgraph(4) utilities like ports/net/mpd or ports/net/mpd4.
 
 20060106:
 	si(4)'s device files now contain the unit number.
 	Uses of {cua,tty}A[0-9a-f] should be replaced by {cua,tty}A0[0-9a-f].
 
 20060106:
 	The kernel ABI was mostly destroyed due to a change in the size
 	of struct lock_object which is nested in other structures such
 	as mutexes which are nested in all sorts of other structures.
 	Make sure your kernel and modules are in sync.
 
 20051231:
 	The page coloring algorithm in the VM subsystem was converted
 	from tuning with kernel options to autotuning. Please remove
 	any PQ_* option except PQ_NOOPT from your kernel config.
 
 20051211:
 	The net80211-related tools in the tools/tools/ath directory
 	have been moved to tools/tools/net80211 and renamed with a
 	"wlan" prefix.  Scripts that use them should be adjusted
 	accordingly.
 
 20051202:
 	Scripts in the local_startup directories (as defined in
 	/etc/defaults/rc.conf) that have the new rc.d semantics will
 	now be run as part of the base system rcorder. If there are
 	errors or problems with one of these local scripts, it could
 	cause boot problems. If you encounter such problems, boot in
 	single user mode, remove that script from the */rc.d directory.
 	Please report the problem to the port's maintainer, and the
 	freebsd-ports@freebsd.org mailing list.
 
 20051129:
 	The nodev mount option was deprecated in RELENG_6 (where it
 	was a no-op), and is now unsupported.  If you have nodev or dev listed
 	in /etc/fstab, remove it, otherwise it will result in a mount error.
 
 20051129:
 	ABI between ipfw(4) and ipfw(8) has been changed. You need
 	to rebuild ipfw(8) when rebuilding kernel.
 
 20051108:
 	rp(4)'s device files now contain the unit number.
 	Uses of {cua,tty}R[0-9a-f] should be replaced by {cua,tty}R0[0-9a-f].
 
 20051029:
 	/etc/rc.d/ppp-user has been renamed to /etc/rc.d/ppp.
 	Its /etc/rc.conf.d configuration file has been `ppp' from
 	the beginning, and hence there is no need to touch it.
 
 20051014:
 	Now most modules get their build-time options from the kernel
 	configuration file.  A few modules still have fixed options
 	due to their non-conformant implementation, but they will be
 	corrected eventually.  You may need to review the options of
 	the modules in use, explicitly specify the non-default options
 	in the kernel configuration file, and rebuild the kernel and
 	modules afterwards.
 
 20051001:
 	kern.polling.enable sysctl MIB is now deprecated. Use ifconfig(8)
 	to turn polling(4) on your interfaces.
 
 20050927:
 	The old bridge(4) implementation was retired.  The new
 	if_bridge(4) serves as a full functional replacement.
 
 20050722:
 	The ai_addrlen of a struct addrinfo was changed to a socklen_t
 	to conform to POSIX-2001.  This change broke an ABI
 	compatibility on 64 bit architecture.  You have to recompile
 	userland programs that use getaddrinfo(3) on 64 bit
 	architecture.
 
 20050711:
 	RELENG_6 branched here.
 
 20050629:
 	The pccard_ifconfig rc.conf variable has been removed and a new
 	variable, ifconfig_DEFAULT has been introduced.  Unlike
 	pccard_ifconfig, ifconfig_DEFAULT applies to ALL interfaces that
 	do not have ifconfig_ifn entries rather than just those in
 	removable_interfaces.
 
 20050616:
 	Some previous versions of PAM have permitted the use of
 	non-absolute paths in /etc/pam.conf or /etc/pam.d/* when referring
 	to third party PAM modules in /usr/local/lib.  A change has been
 	made to require the use of absolute paths in order to avoid
 	ambiguity and dependence on library path configuration, which may
 	affect existing configurations.
 
 20050610:
 	Major changes to network interface API.  All drivers must be
 	recompiled.  Drivers not in the base system will need to be
 	updated to the new APIs.
 
 20050609:
 	Changes were made to kinfo_proc in sys/user.h.  Please recompile
 	userland, or commands like `fstat', `pkill', `ps', `top' and `w'
 	will not behave correctly.
 
 	The API and ABI for hwpmc(4) have changed with the addition
 	of sampling support.  Please recompile lib/libpmc(3) and
 	usr.sbin/{pmcstat,pmccontrol}.
 
 20050606:
 	The OpenBSD dhclient was imported in place of the ISC dhclient
 	and the network interface configuration scripts were updated
 	accordingly.  If you use DHCP to configure your interfaces, you
 	must now run devd.  Also, DNS updating was lost so you will need
 	to find a workaround if you use this feature.
 
 	The '_dhcp' user was added to support the OpenBSD dhclient.  Be
 	sure to run mergemaster -p (like you are supposed to do every time
 	anyway).
 
 20050605:
 	if_bridge was added to the tree. This has changed struct ifnet.
 	Please recompile userland and all network related modules.
 
 20050603:
 	The n_net of a struct netent was changed to an uint32_t, and
 	1st argument of getnetbyaddr() was changed to an uint32_t, to
 	conform to POSIX-2001.  These changes broke an ABI
 	compatibility on 64 bit architecture.  With these changes,
 	shlib major of libpcap was bumped.  You have to recompile
 	userland programs that use getnetbyaddr(3), getnetbyname(3),
 	getnetent(3) and/or libpcap on 64 bit architecture.
 
 20050528:
 	Kernel parsing of extra options on '#!' first lines of shell
 	scripts has changed.  Lines with multiple options likely will
 	fail after this date.  For full details, please see
 		http://people.freebsd.org/~gad/Updating-20050528.txt
 
 20050503:
 	The packet filter (pf) code has been updated to OpenBSD 3.7
 	Please note the changed anchor syntax and the fact that
 	authpf(8) now needs a mounted fdescfs(5) to function.
 
 20050415:
 	The NO_MIXED_MODE kernel option has been removed from the i386
 	amd64 platforms as its use has been superceded by the new local
 	APIC timer code.  Any kernel config files containing this option
 	should be updated.
 
 20050227:
 	The on-disk format of LC_CTYPE files was changed to be machine
 	independent.  Please make sure NOT to use NO_CLEAN buildworld
 	when crossing this point. Crossing this point also requires
 	recompile or reinstall of all locale depended packages.
 
 20050225:
 	The ifi_epoch member of struct if_data has been changed to
 	contain the uptime at which the interface was created or the
 	statistics zeroed rather then the wall clock time because
 	wallclock time may go backwards.  This should have no impact
 	unless an snmp implementation is using this value (I know of
 	none at this point.)
 
 20050224:
 	The acpi_perf and acpi_throttle drivers are now part of the
 	acpi(4) main module.  They are no longer built separately.
 
 20050223:
 	The layout of struct image_params has changed. You have to
 	recompile all compatibility modules (linux, svr4, etc) for use
 	with the new kernel.
 
 20050223:
 	The p4tcc driver has been merged into cpufreq(4).  This makes
 	"options CPU_ENABLE_TCC" obsolete.  Please load cpufreq.ko or
 	compile in "device cpufreq" to restore this functionality.
 
 20050220:
 	The responsibility of recomputing the file system summary of
 	a SoftUpdates-enabled dirty volume has been transferred to the
 	background fsck.  A rebuild of fsck(8) utility is recommended
 	if you have updated the kernel.
 
 	To get the old behavior (recompute file system summary at mount
 	time), you can set vfs.ffs.compute_summary_at_mount=1 before
 	mounting the new volume.
 
 20050206:
 	The cpufreq import is complete.  As part of this, the sysctls for
 	acpi(4) throttling have been removed.  The power_profile script
 	has been updated, so you can use performance/economy_cpu_freq in
 	rc.conf(5) to set AC on/offline cpu frequencies.
 
 20050206:
 	NG_VERSION has been increased. Recompiling kernel (or ng_socket.ko)
 	requires recompiling libnetgraph and userland netgraph utilities.
 
 20050114:
 	Support for abbreviated forms of a number of ipfw options is
 	now deprecated.  Warnings are printed to stderr indicating the
 	correct full form when a match occurs.  Some abbreviations may
 	be supported at a later date based on user feedback.  To be
 	considered for support, abbreviations must be in use prior to
 	this commit and unlikely to be confused with current key words.
 
 20041221:
 	By a popular demand, a lot of NOFOO options were renamed
 	to NO_FOO (see bsd.compat.mk for a full list).  The old
 	spellings are still supported, but will cause annoying
 	warnings on stderr.  Make sure you upgrade properly (see
 	the COMMON ITEMS: section later in this file).
 
 20041219:
 	Auto-loading of ancillary wlan modules such as wlan_wep has
 	been temporarily disabled; you need to statically configure
 	the modules you need into your kernel or explicitly load them
 	prior to use.  Specifically, if you intend to use WEP encryption
 	with an 802.11 device load/configure wlan_wep; if you want to
 	use WPA with the ath driver load/configure wlan_tkip, wlan_ccmp,
 	and wlan_xauth as required.
 
 20041213:
 	The behaviour of ppp(8) has changed slightly.  If lqr is enabled
 	(``enable lqr''), older versions would revert to LCP ECHO mode on
 	negotiation failure.  Now, ``enable echo'' is required for this
 	behaviour.  The ppp version number has been bumped to 3.4.2 to
 	reflect the change.
 
 20041201:
 	The wlan support has been updated to split the crypto support
 	into separate modules.  For static WEP you must configure the
 	wlan_wep module in your system or build and install the module
 	in place where it can be loaded (the kernel will auto-load
 	the module when a wep key is configured).
 
 20041201:
 	The ath driver has been updated to split the tx rate control
 	algorithm into a separate module.  You need to include either
 	ath_rate_onoe or ath_rate_amrr when configuring the kernel.
 
 20041116:
 	Support for systems with an 80386 CPU has been removed.  Please
 	use FreeBSD 5.x or earlier on systems with an 80386.
 
 20041110:
 	We have had a hack which would mount the root filesystem
 	R/W if the device were named 'md*'.  As part of the vnode
 	work I'm doing I have had to remove this hack.  People
 	building systems which use preloaded MD root filesystems
 	may need to insert a "/sbin/mount -u -o rw /dev/md0 /" in
 	their /etc/rc scripts.
 
 20041104:
 	FreeBSD 5.3 shipped here.
 
 20041102:
 	The size of struct tcpcb has changed again due to the removal
 	of RFC1644 T/TCP.  You have to recompile userland programs that
 	read kmem for tcp sockets directly (netstat, sockstat, etc.)
 
 20041022:
 	The size of struct tcpcb has changed.  You have to recompile
 	userland programs that read kmem for tcp sockets directly
 	(netstat, sockstat, etc.)
 
 20041016:
 	RELENG_5 branched here.  For older entries, please see updating
 	in the RELENG_5 branch.
 
 COMMON ITEMS:
 
 	General Notes
 	-------------
 	Avoid using make -j when upgrading.  From time to time in the
 	past there have been problems using -j with buildworld and/or
 	installworld.  This is especially true when upgrading between
 	"distant" versions (eg one that cross a major release boundary
 	or several minor releases, or when several months have passed
 	on the -current branch).
 
 	Sometimes, obscure build problems are the result of environment
 	poisoning.  This can happen because the make utility reads its
 	environment when searching for values for global variables.
 	To run your build attempts in an "environmental clean room",
 	prefix all make commands with 'env -i '.  See the env(1) manual
 	page for more details.
 
 	When upgrading from one major version to another it is generally
 	best to upgrade to the latest code in the currently installed branch
 	first, then do an upgrade to the new branch. This is the best-tested
 	upgrade path, and has the highest probability of being successful.
 	Please try this approach before reporting problems with a major
 	version upgrade.
 
 	ZFS notes
 	---------
 	When upgrading the boot ZFS pool to a new version, always follow
 	these two steps:
 
 	1.) recompile and reinstall the ZFS boot loader and boot block
 	(this is part of "make buildworld" and "make installworld")
 
 	2.) update the ZFS boot block on your boot drive
 
 	The following example updates the ZFS boot block on the first
 	partition (freebsd-boot) of a GPT partitioned drive ad0:
 	"gpart bootcode -p /boot/gptzfsboot -i 1 ad0"
 
 	Non-boot pools do not need these updates.
 
 	To build a kernel
 	-----------------
 	If you are updating from a prior version of FreeBSD (even one just
 	a few days old), you should follow this procedure.  It is the most
 	failsafe as it uses a /usr/obj tree with a fresh mini-buildworld,
 
 	make kernel-toolchain
 	make -DALWAYS_CHECK_MAKE buildkernel KERNCONF=YOUR_KERNEL_HERE
 	make -DALWAYS_CHECK_MAKE installkernel KERNCONF=YOUR_KERNEL_HERE
 
 	To test a kernel once
 	---------------------
 	If you just want to boot a kernel once (because you are not sure
 	if it works, or if you want to boot a known bad kernel to provide
 	debugging information) run
 	make installkernel KERNCONF=YOUR_KERNEL_HERE KODIR=/boot/testkernel
 	nextboot -k testkernel
 
 	To just build a kernel when you know that it won't mess you up
 	--------------------------------------------------------------
 	This assumes you are already running a 5.X system.  Replace
 	${arch} with the architecture of your machine (e.g. "i386",
 	"alpha", "amd64", "ia64", "pc98", "sparc64", etc).
 
 	cd src/sys/${arch}/conf
 	config KERNEL_NAME_HERE
 	cd ../compile/KERNEL_NAME_HERE
 	make depend
 	make
 	make install
 
 	If this fails, go to the "To build a kernel" section.
 
 	To rebuild everything and install it on the current system.
 	-----------------------------------------------------------
 	# Note: sometimes if you are running current you gotta do more than
 	# is listed here if you are upgrading from a really old current.
 
 	
 	make buildworld
 	make kernel KERNCONF=YOUR_KERNEL_HERE
 							[1]
 					[3]
 	mergemaster -p					[5]
 	make installworld
 	mergemaster					[4]
 	make delete-old					[6]
 	
 
 
 	To cross-install current onto a separate partition
 	--------------------------------------------------
 	# In this approach we use a separate partition to hold
 	# current's root, 'usr', and 'var' directories.   A partition
 	# holding "/", "/usr" and "/var" should be about 2GB in
 	# size.
 
 	
 	
 	make buildworld
 	make buildkernel KERNCONF=YOUR_KERNEL_HERE
 	
 	
 	make installworld DESTDIR=${CURRENT_ROOT}
 	make distribution DESTDIR=${CURRENT_ROOT} # if newfs'd
 	make installkernel KERNCONF=YOUR_KERNEL_HERE DESTDIR=${CURRENT_ROOT}
 	cp /etc/fstab ${CURRENT_ROOT}/etc/fstab 		   # if newfs'd
 	
 	
 	
 	
 	
 
 
 	To upgrade in-place from 5.x-stable to current
 	----------------------------------------------
 	
 	make buildworld					[9]
 	make kernel KERNCONF=YOUR_KERNEL_HERE		[8]
 							[1]
 					[3]
 	mergemaster -p					[5]
 	make installworld
 	mergemaster -i					[4]
 	make delete-old					[6]
 	
 
 	Make sure that you've read the UPDATING file to understand the
 	tweaks to various things you need.  At this point in the life
 	cycle of current, things change often and you are on your own
 	to cope.  The defaults can also change, so please read ALL of
 	the UPDATING entries.
 
 	Also, if you are tracking -current, you must be subscribed to
 	freebsd-current@freebsd.org.  Make sure that before you update
 	your sources that you have read and understood all the recent
 	messages there.  If in doubt, please track -stable which has
 	much fewer pitfalls.
 
 	[1] If you have third party modules, such as vmware, you
 	should disable them at this point so they don't crash your
 	system on reboot.
 
 	[3] From the bootblocks, boot -s, and then do
 		fsck -p
 		mount -u /
 		mount -a
 		cd src
 		adjkerntz -i		# if CMOS is wall time
 	Also, when doing a major release upgrade, it is required that
 	you boot into single user mode to do the installworld.
 
 	[4] Note: This step is non-optional.  Failure to do this step
 	can result in a significant reduction in the functionality of the
 	system.  Attempting to do it by hand is not recommended and those
 	that pursue this avenue should read this file carefully, as well
 	as the archives of freebsd-current and freebsd-hackers mailing lists
 	for potential gotchas.
 
 	[5] Usually this step is a noop.  However, from time to time
 	you may need to do this if you get unknown user in the following
 	step.  It never hurts to do it all the time.  You may need to
 	install a new mergemaster (cd src/usr.sbin/mergemaster && make
 	install) after the buildworld before this step if you last updated
 	from current before 20020224 or from -stable before 20020408.
 
 	[6] This only deletes old files and directories. Old libraries
 	can be deleted by "make delete-old-libs", but you have to make
 	sure that no program is using those libraries anymore.
 
 	[8] In order to have a kernel that can run the 4.x binaries
 	needed to do an installworld, you must include the COMPAT_FREEBSD4
 	option in your kernel.  Failure to do so may leave you with a system
 	that is hard to boot to recover. A similar kernel option COMPAT_FREEBSD5
 	is required to run the 5.x binaries on more recent kernels.
 
 	Make sure that you merge any new devices from GENERIC since the
 	last time you updated your kernel config file.
 
 	[9] When checking out sources, you must include the -P flag to have
 	cvs prune empty directories.
 
 	If CPUTYPE is defined in your /etc/make.conf, make sure to use the
 	"?=" instead of the "=" assignment operator, so that buildworld can
 	override the CPUTYPE if it needs to.
 
 	MAKEOBJDIRPREFIX must be defined in an environment variable, and
 	not on the command line, or in /etc/make.conf.  buildworld will
 	warn if it is improperly defined.
 FORMAT:
 
 This file contains a list, in reverse chronological order, of major
 breakages in tracking -current.  It is not guaranteed to be a complete
 list of such breakages, and only contains entries since October 16, 2004.
 If you need to see UPDATING entries from before that date, you will need
 to fetch an UPDATING file from an older FreeBSD release.
 
 Copyright information:
 
 Copyright 1998-2005 M. Warner Losh.  All Rights Reserved.
 
 Redistribution, publication, translation and use, with or without
 modification, in full or in part, in any form or format of this
 document are permitted without further permission from the author.
 
 THIS DOCUMENT IS PROVIDED BY WARNER LOSH ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL WARNER LOSH BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 If you find this document useful, and you want to, you may buy the
 author a beer.
 
 Contact Warner Losh if you have any questions about your use of
 this document.
 
 $FreeBSD$
Index: releng/8.4/crypto/openssl/crypto/bn/bn_print.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/bn/bn_print.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/bn/bn_print.c	(revision 284295)
@@ -1,338 +1,344 @@
 /* crypto/bn/bn_print.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include "bn_lcl.h"
 
 static const char Hex[]="0123456789ABCDEF";
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2hex(const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	char *buf;
 	char *p;
 
+	if (a->neg && BN_is_zero(a)) {
+	    /* "-0" == 3 bytes including NULL terminator */
+	    buf = OPENSSL_malloc(3);
+	} else {
+	    buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
+	}
 	buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2);
 	if (buf == NULL)
 		{
 		BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	p=buf;
 	if (a->neg) *(p++)='-';
 	if (BN_is_zero(a)) *(p++)='0';
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-8; j >= 0; j-=8)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0xff;
 			if (z || (v != 0))
 				{
 				*(p++)=Hex[v>>4];
 				*(p++)=Hex[v&0x0f];
 				z=1;
 				}
 			}
 		}
 	*p='\0';
 err:
 	return(buf);
 	}
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2dec(const BIGNUM *a)
 	{
 	int i=0,num, ok = 0;
 	char *buf=NULL;
 	char *p;
 	BIGNUM *t=NULL;
 	BN_ULONG *bn_data=NULL,*lp;
 
 	/* get an upper bound for the length of the decimal integer
 	 * num <= (BN_num_bits(a) + 1) * log(2)
 	 *     <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1     (rounding error)
 	 *     <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 
 	 */
 	i=BN_num_bits(a)*3;
 	num=(i/10+i/1000+1)+1;
 	bn_data=(BN_ULONG *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
 	buf=(char *)OPENSSL_malloc(num+3);
 	if ((buf == NULL) || (bn_data == NULL))
 		{
 		BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	if ((t=BN_dup(a)) == NULL) goto err;
 
 #define BUF_REMAIN (num+3 - (size_t)(p - buf))
 	p=buf;
 	lp=bn_data;
 	if (BN_is_zero(t))
 		{
 		*(p++)='0';
 		*(p++)='\0';
 		}
 	else
 		{
 		if (BN_is_negative(t))
 			*p++ = '-';
 
 		i=0;
 		while (!BN_is_zero(t))
 			{
 			*lp=BN_div_word(t,BN_DEC_CONV);
 			lp++;
 			}
 		lp--;
 		/* We now have a series of blocks, BN_DEC_NUM chars
 		 * in length, where the last one needs truncation.
 		 * The blocks need to be reversed in order. */
 		BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT1,*lp);
 		while (*p) p++;
 		while (lp != bn_data)
 			{
 			lp--;
 			BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT2,*lp);
 			while (*p) p++;
 			}
 		}
 	ok = 1;
 err:
 	if (bn_data != NULL) OPENSSL_free(bn_data);
 	if (t != NULL) BN_free(t);
 	if (!ok && buf)
 		{
 		OPENSSL_free(buf);
 		buf = NULL;
 		}
 
 	return(buf);
 	}
 
 int BN_hex2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,h,m,i,j,k,c;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isxdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the hex digits, and it is 'i' long */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of hex digests; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=i; /* least significant 'hex' */
 	m=0;
 	h=0;
 	while (j > 0)
 		{
 		m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
 		l=0;
 		for (;;)
 			{
 			c=a[j-m];
 			if ((c >= '0') && (c <= '9')) k=c-'0';
 			else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
 			else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
 			else k=0; /* paranoia */
 			l=(l<<4)|k;
 
 			if (--m <= 0)
 				{
 				ret->d[h++]=l;
 				break;
 				}
 			}
 		j-=(BN_BYTES*2);
 		}
 	ret->top=h;
 	bn_correct_top(ret);
 	ret->neg=neg;
 
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 int BN_dec2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,i,j;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the digits, and it is 'i' long.
 	 * We chop it into BN_DEC_NUM digits at a time */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of digests, a bit of an over expand; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=BN_DEC_NUM-(i%BN_DEC_NUM);
 	if (j == BN_DEC_NUM) j=0;
 	l=0;
 	while (*a)
 		{
 		l*=10;
 		l+= *a-'0';
 		a++;
 		if (++j == BN_DEC_NUM)
 			{
 			BN_mul_word(ret,BN_DEC_CONV);
 			BN_add_word(ret,l);
 			l=0;
 			j=0;
 			}
 		}
 	ret->neg=neg;
 
 	bn_correct_top(ret);
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 #ifndef OPENSSL_NO_BIO
 #ifndef OPENSSL_NO_FP_API
 int BN_print_fp(FILE *fp, const BIGNUM *a)
 	{
 	BIO *b;
 	int ret;
 
 	if ((b=BIO_new(BIO_s_file())) == NULL)
 		return(0);
 	BIO_set_fp(b,fp,BIO_NOCLOSE);
 	ret=BN_print(b,a);
 	BIO_free(b);
 	return(ret);
 	}
 #endif
 
 int BN_print(BIO *bp, const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	int ret=0;
 
 	if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
 	if (BN_is_zero(a) && (BIO_write(bp,"0",1) != 1)) goto end;
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-4; j >= 0; j-=4)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0x0f;
 			if (z || (v != 0))
 				{
 				if (BIO_write(bp,&(Hex[v]),1) != 1)
 					goto end;
 				z=1;
 				}
 			}
 		}
 	ret=1;
 end:
 	return(ret);
 	}
 #endif
Index: releng/8.4/crypto/openssl/crypto/cms/cms_smime.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/cms/cms_smime.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/cms/cms_smime.c	(revision 284295)
@@ -1,841 +1,841 @@
 /* crypto/cms/cms_smime.c */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  */
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include "cms_lcl.h"
 
 static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
 	{
 	unsigned char buf[4096];
 	int r = 0, i;
 	BIO *tmpout = NULL;
 
 	if (out == NULL)
 		tmpout = BIO_new(BIO_s_null());
 	else if (flags & CMS_TEXT)
 		{
 		tmpout = BIO_new(BIO_s_mem());
 		BIO_set_mem_eof_return(tmpout, 0);
 		}
 	else
 		tmpout = out;
 
 	if(!tmpout)
 		{
 		CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* Read all content through chain to process digest, decrypt etc */
 	for (;;)
 	{
 		i=BIO_read(in,buf,sizeof(buf));
 		if (i <= 0)
 			{
 			if (BIO_method_type(in) == BIO_TYPE_CIPHER)
 				{
 				if (!BIO_get_cipher_status(in))
 					goto err;
 				}
 			if (i < 0)
 				goto err;
 			break;
 			}
 				
 		if (tmpout && (BIO_write(tmpout, buf, i) != i))
 			goto err;
 	}
 
 	if(flags & CMS_TEXT)
 		{
 		if(!SMIME_text(tmpout, out))
 			{
 			CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
 			goto err;
 			}
 		}
 
 	r = 1;
 
 	err:
 	if (tmpout && (tmpout != out))
 		BIO_free(tmpout);
 	return r;
 
 	}
 
 static int check_content(CMS_ContentInfo *cms)
 	{
 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
 	if (!pos || !*pos)
 		{
 		CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
 		return 0;
 		}
 	return 1;
 	}
 
 static void do_free_upto(BIO *f, BIO *upto)
 	{
 	if (upto)
 		{
 		BIO *tbio;
 		do 
 			{
 			tbio = BIO_pop(f);
 			BIO_free(f);
 			f = tbio;
 			}
-		while (f != upto);
+		while (f && f != upto);
 		}
 	else
 		BIO_free_all(f);
 	}
 
 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data)
 		{
 		CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
 		return 0;
 		}
 	cont = CMS_dataInit(cms, NULL);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	BIO_free_all(cont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	cms = cms_Data_create();
 	if (!cms)
 		return NULL;
 
 	if (CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 
 	return NULL;
 	}
 
 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest)
 		{
 		CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	if (r)
 		r = cms_DigestedData_do_final(cms, cont, 1);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!md)
 		md = EVP_sha1();
 	cms = cms_DigestedData_create(md);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
 				const unsigned char *key, size_t keylen,
 				BIO *dcont, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
 					CMS_R_TYPE_NOT_ENCRYPTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
 					const unsigned char *key, size_t keylen,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!cipher)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
 		return NULL;
 		}
 	cms = CMS_ContentInfo_new();
 	if (!cms)
 		return NULL;
 	if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
 					X509_STORE *store,
 					STACK_OF(X509) *certs,
 					STACK_OF(X509_CRL) *crls,
 					unsigned int flags)
 	{
 	X509_STORE_CTX ctx;
 	X509 *signer;
 	int i, j, r = 0;
 	CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 	if (!X509_STORE_CTX_init(&ctx, store, signer, certs))
 		{
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_STORE_INIT_ERROR);
 		goto err;
 		}
 	X509_STORE_CTX_set_default(&ctx, "smime_sign");
 	if (crls)
 		X509_STORE_CTX_set0_crls(&ctx, crls);
 
 	i = X509_verify_cert(&ctx);
 	if (i <= 0)
 		{
 		j = X509_STORE_CTX_get_error(&ctx);
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_CERTIFICATE_VERIFY_ERROR);
 		ERR_add_error_data(2, "Verify error:",
 					 X509_verify_cert_error_string(j));
 		goto err;
 		}
 	r = 1;
 	err:
 	X509_STORE_CTX_cleanup(&ctx);
 	return r;
 
 	}
 
 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 		 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
 	{
 	CMS_SignerInfo *si;
 	STACK_OF(CMS_SignerInfo) *sinfos;
 	STACK_OF(X509) *cms_certs = NULL;
 	STACK_OF(X509_CRL) *crls = NULL;
 	X509 *signer;
 	int i, scount = 0, ret = 0;
 	BIO *cmsbio = NULL, *tmpin = NULL;
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	/* Attempt to find all signer certificates */
 
 	sinfos = CMS_get0_SignerInfos(cms);
 
 	if (sk_CMS_SignerInfo_num(sinfos) <= 0)
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
 		goto err;
 		}
 
 	for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 		{
 		si = sk_CMS_SignerInfo_value(sinfos, i);
 		CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 		if (signer)
 			scount++;
 		}
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		scount += CMS_set1_signers_certs(cms, certs, flags);
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
 		goto err;
 		}
 
 	/* Attempt to verify all signers certs */
 
 	if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
 		{
 		cms_certs = CMS_get1_certs(cms);
 		if (!(flags & CMS_NOCRL))
 			crls = CMS_get1_crls(cms);
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (!cms_signerinfo_verify_cert(si, store,
 							cms_certs, crls, flags))
 				goto err;
 			}
 		}
 
 	/* Attempt to verify all SignerInfo signed attribute signatures */
 
 	if (!(flags & CMS_NO_ATTR_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_signed_get_attr_count(si) < 0)
 				continue;
 			if (CMS_SignerInfo_verify(si) <= 0)
 				goto err;
 			}
 		}
 
 	/* Performance optimization: if the content is a memory BIO then
 	 * store its contents in a temporary read only memory BIO. This
 	 * avoids potentially large numbers of slow copies of data which will
 	 * occur when reading from a read write memory BIO when signatures
 	 * are calculated.
 	 */
 
 	if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM))
 		{
 		char *ptr;
 		long len;
 		len = BIO_get_mem_data(dcont, &ptr);
 		tmpin = BIO_new_mem_buf(ptr, len);
 		if (tmpin == NULL)
 			{
 			CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		}
 	else
 		tmpin = dcont;
 		
 
 	cmsbio=CMS_dataInit(cms, tmpin);
 	if (!cmsbio)
 		goto err;
 
 	if (!cms_copy_content(out, cmsbio, flags))
 		goto err;
 
 	if (!(flags & CMS_NO_CONTENT_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)
 				{
 				CMSerr(CMS_F_CMS_VERIFY,
 					CMS_R_CONTENT_VERIFY_ERROR);
 				goto err;
 				}
 			}
 		}
 
 	ret = 1;
 
 	err:
 	
 	if (dcont && (tmpin == dcont))
 		do_free_upto(cmsbio, dcont);
 	else
 		BIO_free_all(cmsbio);
 
 	if (cms_certs)
 		sk_X509_pop_free(cms_certs, X509_free);
 	if (crls)
 		sk_X509_CRL_pop_free(crls, X509_CRL_free);
 
 	return ret;
 	}
 
 int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
 			STACK_OF(X509) *certs,
 			X509_STORE *store, unsigned int flags)
 	{
 	int r;
 	r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
 	if (r <= 0)
 		return r;
 	return cms_Receipt_verify(rcms, ocms);
 	}
 
 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
 						BIO *data, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 
 	cms = CMS_ContentInfo_new();
 	if (!cms || !CMS_SignedData_init(cms))
 		goto merr;
 
 	if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
 		{
 		CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		X509 *x = sk_X509_value(certs, i);
 		if (!CMS_add1_cert(cms, x))
 			goto merr;
 		}
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
 
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 					X509 *signcert, EVP_PKEY *pkey,
 					STACK_OF(X509) *certs,
 					unsigned int flags)
 	{
 	CMS_SignerInfo *rct_si;
 	CMS_ContentInfo *cms = NULL;
 	ASN1_OCTET_STRING **pos, *os;
 	BIO *rct_cont = NULL;
 	int r = 0;
 
 	flags &= ~CMS_STREAM;
 	/* Not really detached but avoids content being allocated */
 	flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
 	if (!pkey || !signcert)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
 		return NULL;
 		}
 
 	/* Initialize signed data */
 
 	cms = CMS_sign(NULL, NULL, certs, NULL, flags);
 	if (!cms)
 		goto err;
 
 	/* Set inner content type to signed receipt */
 	if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
 		goto err;
 
 	rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
 	if (!rct_si)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	os = cms_encode_Receipt(si);
 
 	if (!os)
 		goto err;
 
 	/* Set content to digest */
 	rct_cont = BIO_new_mem_buf(os->data, os->length);
 	if (!rct_cont)
 		goto err;
 
 	/* Add msgSigDigest attribute */
 
 	if (!cms_msgSigDigest_add1(rct_si, si))
 		goto err;
 
 	/* Finalize structure */
 	if (!CMS_final(cms, rct_cont, NULL, flags))
 		goto err;
 
 	/* Set embedded content */
 	pos = CMS_get0_content(cms);
 	*pos = os;
 
 	r = 1;
 
 	err:
 	if (rct_cont)
 		BIO_free(rct_cont);
 	if (r)
 		return cms;
 	CMS_ContentInfo_free(cms);
 	return NULL;
 
 	}
 
 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
 				const EVP_CIPHER *cipher, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 	X509 *recip;
 	cms = CMS_EnvelopedData_create(cipher);
 	if (!cms)
 		goto merr;
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		recip = sk_X509_value(certs, i);
 		if (!CMS_add1_recipient_cert(cms, recip, flags))
 			{
 			CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
 			goto err;
 			}
 		}
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	int debug = 0, ri_match = 0;
 	ris = CMS_get0_RecipientInfos(cms);
 	if (ris)
 		debug = cms->d.envelopedData->encryptedContentInfo->debug;
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
 				continue;
 		ri_match = 1;
 		/* If we have a cert try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
 			{
 			CMS_RecipientInfo_set0_pkey(ri, pk);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_pkey(ri, NULL);
 			if (cert)
 				{
 				/* If not debugging clear any error and
 				 * return success to avoid leaking of
 				 * information useful to MMA
 				 */
 				if (!debug)
 					{
 					ERR_clear_error();
 					return 1;
 					}
 				if (r > 0)
 					return 1;
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			/* If no cert and not debugging don't leave loop
 			 * after first successful decrypt. Always attempt
 			 * to decrypt all recipients to avoid leaking timing
 			 * of a successful decrypt.
 			 */
 			else if (r > 0 && debug)
 				return 1;
 			}
 		}
 	/* If no cert and not debugging always return success */
 	if (ri_match && !cert && !debug)
 		{
 		ERR_clear_error();
 		return 1;
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 
 int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
 				unsigned char *key, size_t keylen,
 				unsigned char *id, size_t idlen)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	ris = CMS_get0_RecipientInfos(cms);
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
 				continue;
 
 		/* If we have an id try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
 			{
 			CMS_RecipientInfo_set0_key(ri, key, keylen);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_key(ri, NULL, 0);
 			if (r > 0)
 				return 1;
 			if (id)
 				{
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			ERR_clear_error();
 			}
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 	
 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
 				BIO *dcont, BIO *out,
 				unsigned int flags)
 	{
 	int r;
 	BIO *cont;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
 		{
 		CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
 		return 0;
 		}
 	if (!dcont && !check_content(cms))
 		return 0;
 	if (flags & CMS_DEBUG_DECRYPT)
 		cms->d.envelopedData->encryptedContentInfo->debug = 1;
 	else
 		cms->d.envelopedData->encryptedContentInfo->debug = 0;
 	if (!pk && !cert && !dcont && !out)
 		return 1;
 	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
 	{
 	BIO *cmsbio;
 	int ret = 0;
 	if (!(cmsbio = CMS_dataInit(cms, dcont)))
 		{
 		CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	SMIME_crlf_copy(data, cmsbio, flags);
 
 	(void)BIO_flush(cmsbio);
 
 
         if (!CMS_dataFinal(cms, cmsbio))
 		{
 		CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR);
 		goto err;
 		}
 
 	ret = 1;
 
 	err:
 	do_free_upto(cmsbio, dcont);
 
 	return ret;
 
 	}
 
 #ifdef ZLIB
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData)
 		{
 		CMSerr(CMS_F_CMS_UNCOMPRESS,
 					CMS_R_TYPE_NOT_COMPRESSED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (comp_nid <= 0)
 		comp_nid = NID_zlib_compression;
 	cms = cms_CompressedData_create(comp_nid);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if (CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 #else
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return 0;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return NULL;
 	}
 
 #endif
Index: releng/8.4/crypto/openssl/crypto/ec/ec2_smpl.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ec2_smpl.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ec2_smpl.c	(revision 284295)
@@ -1,976 +1,977 @@
 /* crypto/ec/ec2_smpl.c */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
  * to the OpenSSL project.
  *
  * The ECC Code is licensed pursuant to the OpenSSL open source
  * license provided below.
  *
  * The software is originally written by Sheueling Chang Shantz and
  * Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 
 #include "ec_lcl.h"
 
 
 const EC_METHOD *EC_GF2m_simple_method(void)
 	{
 	static const EC_METHOD ret = {
 		NID_X9_62_characteristic_two_field,
 		ec_GF2m_simple_group_init,
 		ec_GF2m_simple_group_finish,
 		ec_GF2m_simple_group_clear_finish,
 		ec_GF2m_simple_group_copy,
 		ec_GF2m_simple_group_set_curve,
 		ec_GF2m_simple_group_get_curve,
 		ec_GF2m_simple_group_get_degree,
 		ec_GF2m_simple_group_check_discriminant,
 		ec_GF2m_simple_point_init,
 		ec_GF2m_simple_point_finish,
 		ec_GF2m_simple_point_clear_finish,
 		ec_GF2m_simple_point_copy,
 		ec_GF2m_simple_point_set_to_infinity,
 		0 /* set_Jprojective_coordinates_GFp */,
 		0 /* get_Jprojective_coordinates_GFp */,
 		ec_GF2m_simple_point_set_affine_coordinates,
 		ec_GF2m_simple_point_get_affine_coordinates,
 		ec_GF2m_simple_set_compressed_coordinates,
 		ec_GF2m_simple_point2oct,
 		ec_GF2m_simple_oct2point,
 		ec_GF2m_simple_add,
 		ec_GF2m_simple_dbl,
 		ec_GF2m_simple_invert,
 		ec_GF2m_simple_is_at_infinity,
 		ec_GF2m_simple_is_on_curve,
 		ec_GF2m_simple_cmp,
 		ec_GF2m_simple_make_affine,
 		ec_GF2m_simple_points_make_affine,
 
 		/* the following three method functions are defined in ec2_mult.c */
 		ec_GF2m_simple_mul,
 		ec_GF2m_precompute_mult,
 		ec_GF2m_have_precompute_mult,
 
 		ec_GF2m_simple_field_mul,
 		ec_GF2m_simple_field_sqr,
 		ec_GF2m_simple_field_div,
 		0 /* field_encode */,
 		0 /* field_decode */,
 		0 /* field_set_to_one */ };
 
 	return &ret;
 	}
 
 
 /* Initialize a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_new.
  */
 int ec_GF2m_simple_group_init(EC_GROUP *group)
 	{
 	BN_init(&group->field);
 	BN_init(&group->a);
 	BN_init(&group->b);
 	return 1;
 	}
 
 
 /* Free a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_free.
  */
 void ec_GF2m_simple_group_finish(EC_GROUP *group)
 	{
 	BN_free(&group->field);
 	BN_free(&group->a);
 	BN_free(&group->b);
 	}
 
 
 /* Clear and free a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_clear_free.
  */
 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
 	{
 	BN_clear_free(&group->field);
 	BN_clear_free(&group->a);
 	BN_clear_free(&group->b);
 	group->poly[0] = 0;
 	group->poly[1] = 0;
 	group->poly[2] = 0;
 	group->poly[3] = 0;
 	group->poly[4] = 0;
 	}
 
 
 /* Copy a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_copy.
  */
 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	int i;
 	if (!BN_copy(&dest->field, &src->field)) return 0;
 	if (!BN_copy(&dest->a, &src->a)) return 0;
 	if (!BN_copy(&dest->b, &src->b)) return 0;
 	dest->poly[0] = src->poly[0];
 	dest->poly[1] = src->poly[1];
 	dest->poly[2] = src->poly[2];
 	dest->poly[3] = src->poly[3];
 	dest->poly[4] = src->poly[4];
 	if(bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
 		return 0;
 	if(bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
 		return 0;
 	for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
 	for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
 	return 1;
 	}
 
 
 /* Set the curve parameters of an EC_GROUP structure. */
 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0, i;
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
 	i = BN_GF2m_poly2arr(&group->field, group->poly, 5);
 	if ((i != 5) && (i != 3))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
 		goto err;
 		}
 
 	/* group->a */
 	if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
 	if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
 	for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
 	
 	/* group->b */
 	if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
 	if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
 	for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
 		
 	ret = 1;
   err:
 	return ret;
 	}
 
 
 /* Get the curve parameters of an EC_GROUP structure.
  * If p, a, or b are NULL then there values will not be set but the method will return with success.
  */
 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	
 	if (p != NULL)
 		{
 		if (!BN_copy(p, &group->field)) return 0;
 		}
 
 	if (a != NULL)
 		{
 		if (!BN_copy(a, &group->a)) goto err;
 		}
 
 	if (b != NULL)
 		{
 		if (!BN_copy(b, &group->b)) goto err;
 		}
 	
 	ret = 1;
 	
   err:
 	return ret;
 	}
 
 
 /* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
 	{
 	return BN_num_bits(&group->field)-1;
 	}
 
 
 /* Checks the discriminant of the curve.
  * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
  */
 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *b;
 	BN_CTX *new_ctx = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	b = BN_CTX_get(ctx);
 	if (b == NULL) goto err;
 
 	if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
 	
 	/* check the discriminant:
 	 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
 	 */
 	if (BN_is_zero(b)) goto err;
 
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Initializes an EC_POINT. */
 int ec_GF2m_simple_point_init(EC_POINT *point)
 	{
 	BN_init(&point->X);
 	BN_init(&point->Y);
 	BN_init(&point->Z);
 	return 1;
 	}
 
 
 /* Frees an EC_POINT. */
 void ec_GF2m_simple_point_finish(EC_POINT *point)
 	{
 	BN_free(&point->X);
 	BN_free(&point->Y);
 	BN_free(&point->Z);
 	}
 
 
 /* Clears and frees an EC_POINT. */
 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
 	{
 	BN_clear_free(&point->X);
 	BN_clear_free(&point->Y);
 	BN_clear_free(&point->Z);
 	point->Z_is_one = 0;
 	}
 
 
 /* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (!BN_copy(&dest->X, &src->X)) return 0;
 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
 	dest->Z_is_one = src->Z_is_one;
 
 	return 1;
 	}
 
 
 /* Set an EC_POINT to the point at infinity.  
  * A point at infinity is represented by having Z=0.
  */
 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	point->Z_is_one = 0;
 	BN_zero(&point->Z);
 	return 1;
 	}
 
 
 /* Set the coordinates of an EC_POINT using affine coordinates. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	int ret = 0;	
 	if (x == NULL || y == NULL)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if (!BN_copy(&point->X, x)) goto err;
 	BN_set_negative(&point->X, 0);
 	if (!BN_copy(&point->Y, y)) goto err;
 	BN_set_negative(&point->Y, 0);
 	if (!BN_copy(&point->Z, BN_value_one())) goto err;
 	BN_set_negative(&point->Z, 0);
 	point->Z_is_one = 1;
 	ret = 1;
 
   err:
 	return ret;
 	}
 
 
 /* Gets the affine coordinates of an EC_POINT. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	int ret = 0;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
 		return 0;
 		}
 
 	if (BN_cmp(&point->Z, BN_value_one())) 
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (x != NULL)
 		{
 		if (!BN_copy(x, &point->X)) goto err;
 		BN_set_negative(x, 0);
 		}
 	if (y != NULL)
 		{
 		if (!BN_copy(y, &point->Y)) goto err;
 		BN_set_negative(y, 0);
 		}
 	ret = 1;
 		
  err:
 	return ret;
 	}
 
 
 /* Include patented algorithms. */
 #include "ec2_smpt.c"
 
 
 /* Converts an EC_POINT to an octet string.  
  * If buf is NULL, the encoded length will be returned.
  * If the length len of buf is smaller than required an error will be returned.
  *
  * The point compression section of this function is patented by Certicom Corp. 
  * under US Patent 6,141,420.  Point compression is disabled by default and can 
  * be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at 
  * Configure-time.
  */
 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, i, skip;
 
 #ifndef OPENSSL_EC_BIN_PT_COMP
 	if ((form == POINT_CONVERSION_COMPRESSED) || (form == POINT_CONVERSION_HYBRID)) 
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED);
 		goto err;
 		}
 #endif
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		yxi = BN_CTX_get(ctx);
 		if (yxi == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 
 		buf[0] = form;
 #ifdef OPENSSL_EC_BIN_PT_COMP
 		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (BN_is_odd(yxi)) buf[0]++;
 			}
 #endif
 
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 /* Converts an octet string representation to an EC_POINT. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	yxi = BN_CTX_get(ctx);
 	if (yxi == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (y_bit != BN_is_odd(yxi))
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Computes a + b and stores the result in r.  r could be a or b, a could be b.
  * Uses algorithm A.10.2 of IEEE P1363.
  */
 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
 	int ret = 0;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		if (!EC_POINT_copy(r, b)) return 0;
 		return 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		{
 		if (!EC_POINT_copy(r, a)) return 0;
 		return 1;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x0 = BN_CTX_get(ctx);
 	y0 = BN_CTX_get(ctx);
 	x1 = BN_CTX_get(ctx);
 	y1 = BN_CTX_get(ctx);
 	x2 = BN_CTX_get(ctx);
 	y2 = BN_CTX_get(ctx);
 	s = BN_CTX_get(ctx);
 	t = BN_CTX_get(ctx);
 	if (t == NULL) goto err;
 
 	if (a->Z_is_one) 
 		{
 		if (!BN_copy(x0, &a->X)) goto err;
 		if (!BN_copy(y0, &a->Y)) goto err;
 		}
 	else
 		{
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
 		}
 	if (b->Z_is_one) 
 		{
 		if (!BN_copy(x1, &b->X)) goto err;
 		if (!BN_copy(y1, &b->Y)) goto err;
 		}
 	else
 		{
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
 		}
 
 
 	if (BN_GF2m_cmp(x0, x1))
 		{
 		if (!BN_GF2m_add(t, x0, x1)) goto err;
 		if (!BN_GF2m_add(s, y0, y1)) goto err;
 		if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
 		if (!BN_GF2m_add(x2, x2, s)) goto err;
 		if (!BN_GF2m_add(x2, x2, t)) goto err;
 		}
 	else
 		{
 		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
 			{
 			if (!EC_POINT_set_to_infinity(group, r)) goto err;
 			ret = 1;
 			goto err;
 			}
 		if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
 		if (!BN_GF2m_add(s, s, x1)) goto err;
 		
 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
 		if (!BN_GF2m_add(x2, x2, s)) goto err;
 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
 		}
 
 	if (!BN_GF2m_add(y2, x1, x2)) goto err;
 	if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
 	if (!BN_GF2m_add(y2, y2, x2)) goto err;
 	if (!BN_GF2m_add(y2, y2, y1)) goto err;
 
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Computes 2 * a and stores the result in r.  r could be a.
  * Uses algorithm A.10.2 of IEEE P1363.
  */
 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	return ec_GF2m_simple_add(group, r, a, a, ctx);
 	}
 
 
 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
 		/* point is its own inverse */
 		return 1;
 	
 	if (!EC_POINT_make_affine(group, point, ctx)) return 0;
 	return BN_GF2m_add(&point->Y, &point->X, &point->Y);
 	}
 
 
 /* Indicates whether the given point is the point at infinity. */
 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	return BN_is_zero(&point->Z);
 	}
 
 
 /* Determines whether the given EC_POINT is an actual point on the curve defined
  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
  *      y^2 + x*y = x^3 + a*x^2 + b.
  */
 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
 	{
 	int ret = -1;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *lh, *y2;
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 
 	if (EC_POINT_is_at_infinity(group, point))
 		return 1;
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;	
 
 	/* only support affine coordinates */
 	if (!point->Z_is_one) return -1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	y2 = BN_CTX_get(ctx);
 	lh = BN_CTX_get(ctx);
 	if (lh == NULL) goto err;
 
 	/* We have a curve defined by a Weierstrass equation
 	 *      y^2 + x*y = x^3 + a*x^2 + b.
 	 *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
 	 *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
 	 */
 	if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
 	if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, y2)) goto err;
 	ret = BN_is_zero(lh);
  err:
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Indicates whether two points are equal.
  * Return values:
  *  -1   error
  *   0   equal (in affine coordinates)
  *   1   not equal
  */
 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	BIGNUM *aX, *aY, *bX, *bY;
 	BN_CTX *new_ctx = NULL;
 	int ret = -1;
 
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		return 1;
 	
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	aX = BN_CTX_get(ctx);
 	aY = BN_CTX_get(ctx);
 	bX = BN_CTX_get(ctx);
 	bY = BN_CTX_get(ctx);
 	if (bY == NULL) goto err;
 
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
 	ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
 
   err:	
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Forces the given EC_POINT to internally use affine coordinates. */
 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	int ret = 0;
 
 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
 		return 1;
 	
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 	
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 	if (!BN_copy(&point->X, x)) goto err;
 	if (!BN_copy(&point->Y, y)) goto err;
 	if (!BN_one(&point->Z)) goto err;
 	
 	ret = 1;		
 
   err:
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	size_t i;
 
 	for (i = 0; i < num; i++)
 		{
 		if (!group->meth->make_affine(group, points[i], ctx)) return 0;
 		}
 
 	return 1;
 	}
 
 
 /* Wrapper to simple binary polynomial field multiplication implementation. */
 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
 	}
 
 
 /* Wrapper to simple binary polynomial field squaring implementation. */
 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
 	}
 
 
 /* Wrapper to simple binary polynomial field division implementation. */
 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
 	}
Index: releng/8.4/crypto/openssl/crypto/ec/ec_check.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ec_check.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ec_check.c	(revision 284295)
@@ -1,123 +1,123 @@
 /* crypto/ec/ec_check.c */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include "ec_lcl.h"
 #include 
 
 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *order;
 	BN_CTX *new_ctx = NULL;
 	EC_POINT *point = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	if ((order = BN_CTX_get(ctx)) == NULL) goto err;
 
 	/* check the discriminant */
 	if (!EC_GROUP_check_discriminant(group, ctx))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
 		goto err;
 		}
 
 	/* check the generator */
 	if (group->generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
 		goto err;
 		}
-	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
+	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	/* check the order of the generator */
 	if ((point = EC_POINT_new(group)) == NULL) goto err;
 	if (!EC_GROUP_get_order(group, order, ctx)) goto err; 
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
 		goto err;
 		}
 	
 	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
 	if (!EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	if (point)
 		EC_POINT_free(point);
 	return ret;
 	}
Index: releng/8.4/crypto/openssl/crypto/ec/ec_key.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ec_key.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ec_key.c	(revision 284295)
@@ -1,471 +1,471 @@
 /* crypto/ec/ec_key.c */
 /*
  * Written by Nils Larsch for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions originally developed by SUN MICROSYSTEMS, INC., and 
  * contributed to the OpenSSL project.
  */
 
 #include 
 #include "ec_lcl.h"
 #include 
 
 EC_KEY *EC_KEY_new(void)
 	{
 	EC_KEY *ret;
 
 	ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE);
 		return(NULL);
 		}
 
 	ret->version = 1;	
 	ret->group   = NULL;
 	ret->pub_key = NULL;
 	ret->priv_key= NULL;
 	ret->enc_flag= 0; 
 	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
 	ret->references= 1;
 	ret->method_data = NULL;
 	return(ret);
 	}
 
 EC_KEY *EC_KEY_new_by_curve_name(int nid)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	ret->group = EC_GROUP_new_by_curve_name(nid);
 	if (ret->group == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 void EC_KEY_free(EC_KEY *r)
 	{
 	int i;
 
 	if (r == NULL) return;
 
 	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"EC_KEY_free, bad reference count\n");
 		abort();
 		}
 #endif
 
 	if (r->group    != NULL) 
 		EC_GROUP_free(r->group);
 	if (r->pub_key  != NULL)
 		EC_POINT_free(r->pub_key);
 	if (r->priv_key != NULL)
 		BN_clear_free(r->priv_key);
 
 	EC_EX_DATA_free_all_data(&r->method_data);
 
 	OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
 
 	OPENSSL_free(r);
 	}
 
 EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest == NULL || src == NULL)
 		{
 		ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	/* copy the parameters */
 	if (src->group)
 		{
 		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
 		/* clear the old group */
 		if (dest->group)
 			EC_GROUP_free(dest->group);
 		dest->group = EC_GROUP_new(meth);
 		if (dest->group == NULL)
 			return NULL;
 		if (!EC_GROUP_copy(dest->group, src->group))
 			return NULL;
 		}
 	/*  copy the public key */
 	if (src->pub_key && src->group)
 		{
 		if (dest->pub_key)
 			EC_POINT_free(dest->pub_key);
 		dest->pub_key = EC_POINT_new(src->group);
 		if (dest->pub_key == NULL)
 			return NULL;
 		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
 			return NULL;
 		}
 	/* copy the private key */
 	if (src->priv_key)
 		{
 		if (dest->priv_key == NULL)
 			{
 			dest->priv_key = BN_new();
 			if (dest->priv_key == NULL)
 				return NULL;
 			}
 		if (!BN_copy(dest->priv_key, src->priv_key))
 			return NULL;
 		}
 	/* copy method/extra data */
 	EC_EX_DATA_free_all_data(&dest->method_data);
 
 	for (d = src->method_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	/* copy the rest */
 	dest->enc_flag  = src->enc_flag;
 	dest->conv_form = src->conv_form;
 	dest->version   = src->version;
 
 	return dest;
 	}
 
 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	if (EC_KEY_copy(ret, ec_key) == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 int EC_KEY_up_ref(EC_KEY *r)
 	{
 	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 #ifdef REF_CHECK
 	if (i < 2)
 		{
 		fprintf(stderr, "EC_KEY_up, bad reference count\n");
 		abort();
 		}
 #endif
 	return ((i > 1) ? 1 : 0);
 	}
 
 int EC_KEY_generate_key(EC_KEY *eckey)
 	{	
 	int	ok = 0;
 	BN_CTX	*ctx = NULL;
 	BIGNUM	*priv_key = NULL, *order = NULL;
 	EC_POINT *pub_key = NULL;
 
 	if (!eckey || !eckey->group)
 		{
 		ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if ((order = BN_new()) == NULL) goto err;
 	if ((ctx = BN_CTX_new()) == NULL) goto err;
 
 	if (eckey->priv_key == NULL)
 		{
 		priv_key = BN_new();
 		if (priv_key == NULL)
 			goto err;
 		}
 	else
 		priv_key = eckey->priv_key;
 
 	if (!EC_GROUP_get_order(eckey->group, order, ctx))
 		goto err;
 
 	do
 		if (!BN_rand_range(priv_key, order))
 			goto err;
 	while (BN_is_zero(priv_key));
 
 	if (eckey->pub_key == NULL)
 		{
 		pub_key = EC_POINT_new(eckey->group);
 		if (pub_key == NULL)
 			goto err;
 		}
 	else
 		pub_key = eckey->pub_key;
 
 	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
 		goto err;
 
 	eckey->priv_key = priv_key;
 	eckey->pub_key  = pub_key;
 
 	ok=1;
 
 err:	
 	if (order)
 		BN_free(order);
 	if (pub_key  != NULL && eckey->pub_key  == NULL)
 		EC_POINT_free(pub_key);
 	if (priv_key != NULL && eckey->priv_key == NULL)
 		BN_free(priv_key);
 	if (ctx != NULL)
 		BN_CTX_free(ctx);
 	return(ok);
 	}
 
 int EC_KEY_check_key(const EC_KEY *eckey)
 	{
 	int	ok   = 0;
 	BN_CTX	*ctx = NULL;
 	const BIGNUM	*order  = NULL;
 	EC_POINT *point = NULL;
 
 	if (!eckey || !eckey->group || !eckey->pub_key)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
 		goto err;
 		}
 
 	if ((ctx = BN_CTX_new()) == NULL)
 		goto err;
 	if ((point = EC_POINT_new(eckey->group)) == NULL)
 		goto err;
 
 	/* testing whether the pub_key is on the elliptic curve */
-	if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
+	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 	/* testing whether pub_key * order is the point at infinity */
 	order = &eckey->group->order;
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 		goto err;
 		}
 	if (!EC_POINT_is_at_infinity(eckey->group, point))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 		goto err;
 		}
 	/* in case the priv_key is present : 
 	 * check if generator * priv_key == pub_key 
 	 */
 	if (eckey->priv_key)
 		{
 		if (BN_cmp(eckey->priv_key, order) >= 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 			goto err;
 			}
 		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
 			NULL, NULL, ctx))
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 
 			ctx) != 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
 			goto err;
 			}
 		}
 	ok = 1;
 err:
 	if (ctx   != NULL)
 		BN_CTX_free(ctx);
 	if (point != NULL)
 		EC_POINT_free(point);
 	return(ok);
 	}
 
 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
 	{
 	return key->group;
 	}
 
 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
 	{
 	if (key->group != NULL)
 		EC_GROUP_free(key->group);
 	key->group = EC_GROUP_dup(group);
 	return (key->group == NULL) ? 0 : 1;
 	}
 
 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
 	{
 	return key->priv_key;
 	}
 
 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
 	{
 	if (key->priv_key)
 		BN_clear_free(key->priv_key);
 	key->priv_key = BN_dup(priv_key);
 	return (key->priv_key == NULL) ? 0 : 1;
 	}
 
 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
 	{
 	return key->pub_key;
 	}
 
 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
 	{
 	if (key->pub_key != NULL)
 		EC_POINT_free(key->pub_key);
 	key->pub_key = EC_POINT_dup(pub_key, key->group);
 	return (key->pub_key == NULL) ? 0 : 1;
 	}
 
 unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
 	{
 	return key->enc_flag;
 	}
 
 void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
 	{
 	key->enc_flag = flags;
 	}
 
 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
 	{
 	return key->conv_form;
 	}
 
 void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
 	{
 	key->conv_form = cform;
 	if (key->group != NULL)
 		EC_GROUP_set_point_conversion_form(key->group, cform);
 	}
 
 void *EC_KEY_get_key_method_data(EC_KEY *key,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	void *ret;
 
 	CRYPTO_r_lock(CRYPTO_LOCK_EC);
 	ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	CRYPTO_r_unlock(CRYPTO_LOCK_EC);
 
 	return ret;
 	}
 
 void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *ex_data;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_EC);
 	ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	if (ex_data == NULL)
 		EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
 	CRYPTO_w_unlock(CRYPTO_LOCK_EC);
 
 	return ex_data;
 	}
 
 void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
 	{
 	if (key->group != NULL)
 		EC_GROUP_set_asn1_flag(key->group, flag);
 	}
 
 int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
 	{
 	if (key->group == NULL)
 		return 0;
 	return EC_GROUP_precompute_mult(key->group, ctx);
 	}
Index: releng/8.4/crypto/openssl/crypto/ec/ec_lib.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ec_lib.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ec_lib.c	(revision 284295)
@@ -1,1164 +1,1172 @@
 /* crypto/ec/ec_lib.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Binary polynomial ECC support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #include 
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
 
 
 /* functions for EC_GROUP objects */
 
 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
 	{
 	EC_GROUP *ret;
 
 	if (meth == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	if (meth->group_init == 0)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = meth;
 
 	ret->extra_data = NULL;
 
 	ret->generator = NULL;
 	BN_init(&ret->order);
 	BN_init(&ret->cofactor);
 
 	ret->curve_name = 0;	
 	ret->asn1_flag  = 0;
 	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
 
 	ret->seed = NULL;
 	ret->seed_len = 0;
 
 	if (!meth->group_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_GROUP_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_free(group->generator);
 	BN_free(&group->order);
 	BN_free(&group->cofactor);
 
 	if (group->seed)
 		OPENSSL_free(group->seed);
 
 	OPENSSL_free(group);
 	}
  
 
 void EC_GROUP_clear_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_clear_finish != 0)
 		group->meth->group_clear_finish(group);
 	else if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_clear_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_clear_free(group->generator);
 	BN_clear_free(&group->order);
 	BN_clear_free(&group->cofactor);
 
 	if (group->seed)
 		{
 		OPENSSL_cleanse(group->seed, group->seed_len);
 		OPENSSL_free(group->seed);
 		}
 
 	OPENSSL_cleanse(group, sizeof *group);
 	OPENSSL_free(group);
 	}
 
 
 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest->meth->group_copy == 0)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	
 	EC_EX_DATA_free_all_data(&dest->extra_data);
 
 	for (d = src->extra_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	if (src->generator != NULL)
 		{
 		if (dest->generator == NULL)
 			{
 			dest->generator = EC_POINT_new(dest);
 			if (dest->generator == NULL) return 0;
 			}
 		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
 		}
 	else
 		{
 		/* src->generator == NULL */
 		if (dest->generator != NULL)
 			{
 			EC_POINT_clear_free(dest->generator);
 			dest->generator = NULL;
 			}
 		}
 
 	if (!BN_copy(&dest->order, &src->order)) return 0;
 	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
 
 	dest->curve_name = src->curve_name;
 	dest->asn1_flag  = src->asn1_flag;
 	dest->asn1_form  = src->asn1_form;
 
 	if (src->seed)
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = OPENSSL_malloc(src->seed_len);
 		if (dest->seed == NULL)
 			return 0;
 		if (!memcpy(dest->seed, src->seed, src->seed_len))
 			return 0;
 		dest->seed_len = src->seed_len;
 		}
 	else
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = NULL;
 		dest->seed_len = 0;
 		}
 	
 
 	return dest->meth->group_copy(dest, src);
 	}
 
 
 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
 	{
 	EC_GROUP *t = NULL;
 	int ok = 0;
 
 	if (a == NULL) return NULL;
 
 	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
 	if (!EC_GROUP_copy(t, a)) goto err;
 
 	ok = 1;
 
   err:	
 	if (!ok)
 		{
 		if (t) EC_GROUP_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
 	{
 	return group->meth;
 	}
 
 
 int EC_METHOD_get_field_type(const EC_METHOD *meth)
         {
         return meth->field_type;
         }
 
 
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
 	{
 	if (generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
 		return 0   ;
 		}
 
 	if (group->generator == NULL)
 		{
 		group->generator = EC_POINT_new(group);
 		if (group->generator == NULL) return 0;
 		}
 	if (!EC_POINT_copy(group->generator, generator)) return 0;
 
 	if (order != NULL)
 		{ if (!BN_copy(&group->order, order)) return 0; }	
 	else
 		BN_zero(&group->order);
 
 	if (cofactor != NULL)
 		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }	
 	else
 		BN_zero(&group->cofactor);
 
 	return 1;
 	}
 
 
 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
 	{
 	return group->generator;
 	}
 
 
 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
 	{
 	if (!BN_copy(order, &group->order))
 		return 0;
 
 	return !BN_is_zero(order);
 	}
 
 
 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
 	{
 	if (!BN_copy(cofactor, &group->cofactor))
 		return 0;
 
 	return !BN_is_zero(&group->cofactor);
 	}
 
 
 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
 	{
 	group->curve_name = nid;
 	}
 
 
 int EC_GROUP_get_curve_name(const EC_GROUP *group)
 	{
 	return group->curve_name;
 	}
 
 
 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
 	{
 	group->asn1_flag = flag;
 	}
 
 
 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
 	{
 	return group->asn1_flag;
 	}
 
 
 void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 
                                         point_conversion_form_t form)
 	{
 	group->asn1_form = form;
 	}
 
 
 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
 	{
 	return group->asn1_form;
 	}
 
 
 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
 	{
 	if (group->seed)
 		{
 		OPENSSL_free(group->seed);
 		group->seed = NULL;
 		group->seed_len = 0;
 		}
 
 	if (!len || !p)
 		return 1;
 
 	if ((group->seed = OPENSSL_malloc(len)) == NULL)
 		return 0;
 	memcpy(group->seed, p, len);
 	group->seed_len = len;
 
 	return len;
 	}
 
 
 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
 	{
 	return group->seed;
 	}
 
 
 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
 	{
 	return group->seed_len;
 	}
 
 
 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_degree(const EC_GROUP *group)
 	{
 	if (group->meth->group_get_degree == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_degree(group);
 	}
 
 
 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->group_check_discriminant == 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_check_discriminant(group, ctx);
 	}
 
 
 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
 	{
 	int    r = 0;
 	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
 	BN_CTX *ctx_new = NULL;
 
 	/* compare the field types*/
 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
 	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
 		return 1;
 	/* compare the curve name (if present in both) */
 	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
 	    EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
 		return 1;
 
 	if (!ctx)
 		ctx_new = ctx = BN_CTX_new();
 	if (!ctx)
 		return -1;
 	
 	BN_CTX_start(ctx);
 	a1 = BN_CTX_get(ctx);
 	a2 = BN_CTX_get(ctx);
 	a3 = BN_CTX_get(ctx);
 	b1 = BN_CTX_get(ctx);
 	b2 = BN_CTX_get(ctx);
 	b3 = BN_CTX_get(ctx);
 	if (!b3)
 		{
 		BN_CTX_end(ctx);
 		if (ctx_new)
 			BN_CTX_free(ctx);
 		return -1;
 		}
 
 	/* XXX This approach assumes that the external representation
 	 * of curves over the same field type is the same.
 	 */
 	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
 	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
 		r = 1;
 
 	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
 		r = 1;
 
 	/* XXX EC_POINT_cmp() assumes that the methods are equal */
 	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
 	    EC_GROUP_get0_generator(b), ctx))
 		r = 1;
 
 	if (!r)
 		{
 		/* compare the order and cofactor */
 		if (!EC_GROUP_get_order(a, a1, ctx) ||
 		    !EC_GROUP_get_order(b, b1, ctx) ||
 		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
 		    !EC_GROUP_get_cofactor(b, b2, ctx))
 			{
 			BN_CTX_end(ctx);
 			if (ctx_new)
 				BN_CTX_free(ctx);
 			return -1;
 			}
 		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
 			r = 1;
 		}
 
 	BN_CTX_end(ctx);
 	if (ctx_new)
 		BN_CTX_free(ctx);
 
 	return r;
 	}
 
 
 /* this has 'package' visibility */
 int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return 0;
 
 	for (d = *ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			{
 			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
 			return 0;
 			}
 		}
 
 	if (data == NULL)
 		/* no explicit entry needed */
 		return 1;
 
 	d = OPENSSL_malloc(sizeof *d);
 	if (d == NULL)
 		return 0;
 
 	d->data = data;
 	d->dup_func = dup_func;
 	d->free_func = free_func;
 	d->clear_free_func = clear_free_func;
 
 	d->next = *ex_data;
 	*ex_data = d;
 
 	return 1;
 	}
 
 /* this has 'package' visibility */
 void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	const EC_EXTRA_DATA *d;
 
 	for (d = ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			return d->data;
 		}
 	
 	return NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->clear_free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->clear_free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 
 /* functions for EC_POINT objects */
 
 EC_POINT *EC_POINT_new(const EC_GROUP *group)
 	{
 	EC_POINT *ret;
 
 	if (group == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	if (group->meth->point_init == 0)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = group->meth;
 	
 	if (!ret->meth->point_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_POINT_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_free(point);
 	}
  
 
 void EC_POINT_clear_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_clear_finish != 0)
 		point->meth->point_clear_finish(point);
 	else if (point->meth != NULL && point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_cleanse(point, sizeof *point);
 	OPENSSL_free(point);
 	}
 
 
 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (dest->meth->point_copy == 0)
 		{
 		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	return dest->meth->point_copy(dest, src);
 	}
 
 
 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
 	{
 	EC_POINT *t;
 	int r;
 
 	if (a == NULL) return NULL;
 
 	t = EC_POINT_new(group);
 	if (t == NULL) return(NULL);
 	r = EC_POINT_copy(t, a);
 	if (!r)
 		{
 		EC_POINT_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
 	{
 	return point->meth;
 	}
 
 
 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	if (group->meth->point_set_to_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_to_infinity(group, point);
 	}
 
 
 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, int y_bit, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_compressed_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
 	}
 
 
 int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, int y_bit, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_compressed_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
 	}
 
 
 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
         unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	if (group->meth->point2oct == 0)
 		{
 		ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point2oct(group, point, form, buf, len, ctx);
 	}
 
 
 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
         const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	if (group->meth->oct2point == 0)
 		{
 		ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->oct2point(group, point, buf, len, ctx);
 	}
 
 
 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->add == 0)
 		{
 		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->add(group, r, a, b, ctx);
 	}
 
 
 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->dbl == 0)
 		{
 		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth))
 		{
 		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->dbl(group, r, a, ctx);
 	}
 
 
 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->invert == 0)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != a->meth)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->invert(group, a, ctx);
 	}
 
 
 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	if (group->meth->is_at_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_at_infinity(group, point);
 	}
 
 
-int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+/*
+ * Check whether an EC_POINT is on the curve or not. Note that the return
+ * value for this function should NOT be treated as a boolean. Return values:
+ *  1: The point is on the curve
+ *  0: The point is not on the curve
+ * -1: An error occurred
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+                         BN_CTX *ctx)
 	{
 	if (group->meth->is_on_curve == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_on_curve(group, point, ctx);
 	}
 
 
 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->point_cmp == 0)
 		{
 		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return -1;
 		}
 	if ((group->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
 		return -1;
 		}
 	return group->meth->point_cmp(group, a, b, ctx);
 	}
 
 
 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (group->meth->make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->make_affine(group, point, ctx);
 	}
 
 
 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	size_t i;
 
 	if (group->meth->points_make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	for (i = 0; i < num; i++)
 		{
 		if (group->meth != points[i]->meth)
 			{
 			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 			return 0;
 			}
 		}
 	return group->meth->points_make_affine(group, num, points, ctx);
 	}
 
 
 /* Functions for point multiplication.
  *
  * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
  * otherwise we dispatch through methods.
  */
 
 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
 	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
 
 	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
 	}
 
 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
 	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
 	{
 	/* just a convenient interface to EC_POINTs_mul() */
 
 	const EC_POINT *points[1];
 	const BIGNUM *scalars[1];
 
 	points[0] = point;
 	scalars[0] = p_scalar;
 
 	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
 	}
 
 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_precompute_mult(group, ctx);
 
 	if (group->meth->precompute_mult != 0)
 		return group->meth->precompute_mult(group, ctx);
 	else
 		return 1; /* nothing to do, so report success */
 	}
 
 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_have_precompute_mult(group);
 
 	if (group->meth->have_precompute_mult != 0)
 		return group->meth->have_precompute_mult(group);
 	else
 		return 0; /* cannot tell whether precomputation has been performed */
 	}
Index: releng/8.4/crypto/openssl/crypto/ec/ecp_smpl.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ecp_smpl.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ecp_smpl.c	(revision 284295)
@@ -1,1697 +1,1698 @@
 /* crypto/ec/ecp_smpl.c */
 /* Includes code written by Lenka Fibikova 
  * for the OpenSSL project. 
  * Includes code written by Bodo Moeller for the OpenSSL project.
 */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
  * and contributed to the OpenSSL project.
  */
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 const EC_METHOD *EC_GFp_simple_method(void)
 	{
 	static const EC_METHOD ret = {
 		NID_X9_62_prime_field,
 		ec_GFp_simple_group_init,
 		ec_GFp_simple_group_finish,
 		ec_GFp_simple_group_clear_finish,
 		ec_GFp_simple_group_copy,
 		ec_GFp_simple_group_set_curve,
 		ec_GFp_simple_group_get_curve,
 		ec_GFp_simple_group_get_degree,
 		ec_GFp_simple_group_check_discriminant,
 		ec_GFp_simple_point_init,
 		ec_GFp_simple_point_finish,
 		ec_GFp_simple_point_clear_finish,
 		ec_GFp_simple_point_copy,
 		ec_GFp_simple_point_set_to_infinity,
 		ec_GFp_simple_set_Jprojective_coordinates_GFp,
 		ec_GFp_simple_get_Jprojective_coordinates_GFp,
 		ec_GFp_simple_point_set_affine_coordinates,
 		ec_GFp_simple_point_get_affine_coordinates,
 		ec_GFp_simple_set_compressed_coordinates,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		ec_GFp_simple_add,
 		ec_GFp_simple_dbl,
 		ec_GFp_simple_invert,
 		ec_GFp_simple_is_at_infinity,
 		ec_GFp_simple_is_on_curve,
 		ec_GFp_simple_cmp,
 		ec_GFp_simple_make_affine,
 		ec_GFp_simple_points_make_affine,
 		0 /* mul */,
 		0 /* precompute_mult */,
 		0 /* have_precompute_mult */,	
 		ec_GFp_simple_field_mul,
 		ec_GFp_simple_field_sqr,
 		0 /* field_div */,
 		0 /* field_encode */,
 		0 /* field_decode */,
 		0 /* field_set_to_one */ };
 
 	return &ret;
 	}
 
 
 /* Most method functions in this file are designed to work with
  * non-trivial representations of field elements if necessary
  * (see ecp_mont.c): while standard modular addition and subtraction
  * are used, the field_mul and field_sqr methods will be used for
  * multiplication, and field_encode and field_decode (if defined)
  * will be used for converting between representations.
 
  * Functions ec_GFp_simple_points_make_affine() and
  * ec_GFp_simple_point_get_affine_coordinates() specifically assume
  * that if a non-trivial representation is used, it is a Montgomery
  * representation (i.e. 'encoding' means multiplying by some factor R).
  */
 
 
 int ec_GFp_simple_group_init(EC_GROUP *group)
 	{
 	BN_init(&group->field);
 	BN_init(&group->a);
 	BN_init(&group->b);
 	group->a_is_minus3 = 0;
 	return 1;
 	}
 
 
 void ec_GFp_simple_group_finish(EC_GROUP *group)
 	{
 	BN_free(&group->field);
 	BN_free(&group->a);
 	BN_free(&group->b);
 	}
 
 
 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
 	{
 	BN_clear_free(&group->field);
 	BN_clear_free(&group->a);
 	BN_clear_free(&group->b);
 	}
 
 
 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	if (!BN_copy(&dest->field, &src->field)) return 0;
 	if (!BN_copy(&dest->a, &src->a)) return 0;
 	if (!BN_copy(&dest->b, &src->b)) return 0;
 
 	dest->a_is_minus3 = src->a_is_minus3;
 
 	return 1;
 	}
 
 
 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp_a;
 	
 	/* p must be a prime > 3 */
 	if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	tmp_a = BN_CTX_get(ctx);
 	if (tmp_a == NULL) goto err;
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
 	BN_set_negative(&group->field, 0);
 
 	/* group->a */
 	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
 	if (group->meth->field_encode)
 		{ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }	
 	else
 		if (!BN_copy(&group->a, tmp_a)) goto err;
 	
 	/* group->b */
 	if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
 	if (group->meth->field_encode)
 		if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
 	
 	/* group->a_is_minus3 */
 	if (!BN_add_word(tmp_a, 3)) goto err;
 	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BN_CTX *new_ctx = NULL;
 	
 	if (p != NULL)
 		{
 		if (!BN_copy(p, &group->field)) return 0;
 		}
 
 	if (a != NULL || b != NULL)
 		{
 		if (group->meth->field_decode)
 			{
 			if (ctx == NULL)
 				{
 				ctx = new_ctx = BN_CTX_new();
 				if (ctx == NULL)
 					return 0;
 				}
 			if (a != NULL)
 				{
 				if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
 				}
 			if (b != NULL)
 				{
 				if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
 				}
 			}
 		else
 			{
 			if (a != NULL)
 				{
 				if (!BN_copy(a, &group->a)) goto err;
 				}
 			if (b != NULL)
 				{
 				if (!BN_copy(b, &group->b)) goto err;
 				}
 			}
 		}
 	
 	ret = 1;
 	
  err:
 	if (new_ctx)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
 	{
 	return BN_num_bits(&group->field);
 	}
 
 
 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
 	const BIGNUM *p = &group->field;
 	BN_CTX *new_ctx = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	a = BN_CTX_get(ctx);
 	b = BN_CTX_get(ctx);
 	tmp_1 = BN_CTX_get(ctx);
 	tmp_2 = BN_CTX_get(ctx);
 	order = BN_CTX_get(ctx);
 	if (order == NULL) goto err;
 
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
 		if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_copy(a, &group->a)) goto err;
 		if (!BN_copy(b, &group->b)) goto err;
 		}
 	
 	/* check the discriminant:
 	 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) 
          * 0 =< a, b < p */
 	if (BN_is_zero(a))
 		{
 		if (BN_is_zero(b)) goto err;
 		}
 	else if (!BN_is_zero(b))
 		{
 		if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
 		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
 		if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
 		/* tmp_1 = 4*a^3 */
 
 		if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
 		if (!BN_mul_word(tmp_2, 27)) goto err;
 		/* tmp_2 = 27*b^2 */
 
 		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
 		if (BN_is_zero(a)) goto err;
 		}
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_point_init(EC_POINT *point)
 	{
 	BN_init(&point->X);
 	BN_init(&point->Y);
 	BN_init(&point->Z);
 	point->Z_is_one = 0;
 
 	return 1;
 	}
 
 
 void ec_GFp_simple_point_finish(EC_POINT *point)
 	{
 	BN_free(&point->X);
 	BN_free(&point->Y);
 	BN_free(&point->Z);
 	}
 
 
 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
 	{
 	BN_clear_free(&point->X);
 	BN_clear_free(&point->Y);
 	BN_clear_free(&point->Z);
 	point->Z_is_one = 0;
 	}
 
 
 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (!BN_copy(&dest->X, &src->X)) return 0;
 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
 	dest->Z_is_one = src->Z_is_one;
 
 	return 1;
 	}
 
 
 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	point->Z_is_one = 0;
 	BN_zero(&point->Z);
 	return 1;
 	}
 
 
 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	int ret = 0;
 	
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	if (x != NULL)
 		{
 		if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
 		if (group->meth->field_encode)
 			{
 			if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
 			}
 		}
 	
 	if (y != NULL)
 		{
 		if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
 		if (group->meth->field_encode)
 			{
 			if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
 			}
 		}
 	
 	if (z != NULL)
 		{
 		int Z_is_one;
 
 		if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
 		Z_is_one = BN_is_one(&point->Z);
 		if (group->meth->field_encode)
 			{
 			if (Z_is_one && (group->meth->field_set_to_one != 0))
 				{
 				if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
 				}
 			else
 				{
 				if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
 				}
 			}
 		point->Z_is_one = Z_is_one;
 		}
 	
 	ret = 1;
 	
  err:
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	int ret = 0;
 	
 	if (group->meth->field_decode != 0)
 		{
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		if (x != NULL)
 			{
 			if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
 			}
 		if (y != NULL)
 			{
 			if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
 			}
 		if (z != NULL)
 			{
 			if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
 			}
 		}
 	else	
 		{
 		if (x != NULL)
 			{
 			if (!BN_copy(x, &point->X)) goto err;
 			}
 		if (y != NULL)
 			{
 			if (!BN_copy(y, &point->Y)) goto err;
 			}
 		if (z != NULL)
 			{
 			if (!BN_copy(z, &point->Z)) goto err;
 			}
 		}
 	
 	ret = 1;
 
  err:
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (x == NULL || y == NULL)
 		{
 		/* unlike for projective coordinates, we do not tolerate this */
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
 	}
 
 
 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
 	const BIGNUM *Z_;
 	int ret = 0;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	Z = BN_CTX_get(ctx);
 	Z_1 = BN_CTX_get(ctx);
 	Z_2 = BN_CTX_get(ctx);
 	Z_3 = BN_CTX_get(ctx);
 	if (Z_3 == NULL) goto err;
 
 	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
 	
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
 		Z_ = Z;
 		}
 	else
 		{
 		Z_ = &point->Z;
 		}
 	
 	if (BN_is_one(Z_))
 		{
 		if (group->meth->field_decode)
 			{
 			if (x != NULL)
 				{
 				if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
 				}
 			if (y != NULL)
 				{
 				if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
 				}
 			}
 		else
 			{
 			if (x != NULL)
 				{
 				if (!BN_copy(x, &point->X)) goto err;
 				}
 			if (y != NULL)
 				{
 				if (!BN_copy(y, &point->Y)) goto err;
 				}
 			}
 		}
 	else
 		{
 		if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
 			goto err;
 			}
 		
 		if (group->meth->field_encode == 0)
 			{
 			/* field_sqr works on standard representation */
 			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
 			}
 	
 		if (x != NULL)
 			{
 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
 			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
 			}
 
 		if (y != NULL)
 			{
 			if (group->meth->field_encode == 0)
 				{
 				/* field_mul works on standard representation */
 				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
 				}
 			else
 				{
 				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
 				}
 
 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
 			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
 			}
 		}
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp1, *tmp2, *x, *y;
 	int ret = 0;
 
 	/* clear error queue*/
 	ERR_clear_error();
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	y_bit = (y_bit != 0);
 
 	BN_CTX_start(ctx);
 	tmp1 = BN_CTX_get(ctx);
 	tmp2 = BN_CTX_get(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	/* Recover y.  We have a Weierstrass equation
 	 *     y^2 = x^3 + a*x + b,
 	 * so  y  is one of the square roots of  x^3 + a*x + b.
 	 */
 
 	/* tmp1 := x^3 */
 	if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
 	if (group->meth->field_decode == 0)
 		{
 		/* field_{sqr,mul} work on standard representation */
 		if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
 		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
 		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + a*x */
 	if (group->a_is_minus3)
 		{
 		if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
 		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
 		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (group->meth->field_decode)
 			{
 			if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
 			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
 			}
 		else
 			{
 			/* field_mul works on standard representation */
 			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
 			}
 		
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + b */
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
 		}
 	
 	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
 		{
 		unsigned long err = ERR_peek_last_error();
 		
 		if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
 			{
 			ERR_clear_error();
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			}
 		else
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
 		goto err;
 		}
 
 	if (y_bit != BN_is_odd(y))
 		{
 		if (BN_is_zero(y))
 			{
 			int kron;
 
 			kron = BN_kronecker(x, &group->field, ctx);
 			if (kron == -2) goto err;
 
 			if (kron == 1)
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
 			else
 				/* BN_mod_sqrt() should have cought this error (not a square) */
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			goto err;
 			}
 		if (!BN_usub(y, &group->field, y)) goto err;
 		}
 	if (y_bit != BN_is_odd(y))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y;
 	size_t field_len, i, skip;
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = BN_num_bytes(&group->field);
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		if (y == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
 			buf[0] = form + 1;
 		else
 			buf[0] = form;
 	
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = BN_num_bytes(&group->field);
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (y_bit != BN_is_odd(y))
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
 	int ret = 0;
 	
 	if (a == b)
 		return EC_POINT_dbl(group, r, a, ctx);
 	if (EC_POINT_is_at_infinity(group, a))
 		return EC_POINT_copy(r, b);
 	if (EC_POINT_is_at_infinity(group, b))
 		return EC_POINT_copy(r, a);
 	
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	n0 = BN_CTX_get(ctx);
 	n1 = BN_CTX_get(ctx);
 	n2 = BN_CTX_get(ctx);
 	n3 = BN_CTX_get(ctx);
 	n4 = BN_CTX_get(ctx);
 	n5 = BN_CTX_get(ctx);
 	n6 = BN_CTX_get(ctx);
 	if (n6 == NULL) goto end;
 
 	/* Note that in this function we must not read components of 'a' or 'b'
 	 * once we have written the corresponding components of 'r'.
 	 * ('r' might be one of 'a' or 'b'.)
 	 */
 
 	/* n1, n2 */
 	if (b->Z_is_one)
 		{
 		if (!BN_copy(n1, &a->X)) goto end;
 		if (!BN_copy(n2, &a->Y)) goto end;
 		/* n1 = X_a */
 		/* n2 = Y_a */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
 		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
 		/* n1 = X_a * Z_b^2 */
 
 		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
 		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
 		/* n2 = Y_a * Z_b^3 */
 		}
 
 	/* n3, n4 */
 	if (a->Z_is_one)
 		{
 		if (!BN_copy(n3, &b->X)) goto end;
 		if (!BN_copy(n4, &b->Y)) goto end;
 		/* n3 = X_b */
 		/* n4 = Y_b */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
 		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
 		/* n3 = X_b * Z_a^2 */
 
 		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
 		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
 		/* n4 = Y_b * Z_a^3 */
 		}
 
 	/* n5, n6 */
 	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
 	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
 	/* n5 = n1 - n3 */
 	/* n6 = n2 - n4 */
 
 	if (BN_is_zero(n5))
 		{
 		if (BN_is_zero(n6))
 			{
 			/* a is the same point as b */
 			BN_CTX_end(ctx);
 			ret = EC_POINT_dbl(group, r, a, ctx);
 			ctx = NULL;
 			goto end;
 			}
 		else
 			{
 			/* a is the inverse of b */
 			BN_zero(&r->Z);
 			r->Z_is_one = 0;
 			ret = 1;
 			goto end;
 			}
 		}
 
 	/* 'n7', 'n8' */
 	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
 	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
 	/* 'n7' = n1 + n3 */
 	/* 'n8' = n2 + n4 */
 
 	/* Z_r */
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		if (!BN_copy(&r->Z, n5)) goto end;
 		}
 	else
 		{
 		if (a->Z_is_one)
 			{ if (!BN_copy(n0, &b->Z)) goto end; }
 		else if (b->Z_is_one)
 			{ if (!BN_copy(n0, &a->Z)) goto end; }
 		else
 			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
 		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
 		}
 	r->Z_is_one = 0;
 	/* Z_r = Z_a * Z_b * n5 */
 
 	/* X_r */
 	if (!field_sqr(group, n0, n6, ctx)) goto end;
 	if (!field_sqr(group, n4, n5, ctx)) goto end;
 	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
 	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
 	/* X_r = n6^2 - n5^2 * 'n7' */
 	
 	/* 'n9' */
 	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
 	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
 	/* n9 = n5^2 * 'n7' - 2 * X_r */
 
 	/* Y_r */
 	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
 	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
 	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
 	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
 	if (BN_is_odd(n0))
 		if (!BN_add(n0, n0, p)) goto end;
 	/* now  0 <= n0 < 2*p,  and n0 is even */
 	if (!BN_rshift1(&r->Y, n0)) goto end;
 	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
 
 	ret = 1;
 
  end:
 	if (ctx) /* otherwise we already called BN_CTX_end */
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *n0, *n1, *n2, *n3;
 	int ret = 0;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		BN_zero(&r->Z);
 		r->Z_is_one = 0;
 		return 1;
 		}
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	n0 = BN_CTX_get(ctx);
 	n1 = BN_CTX_get(ctx);
 	n2 = BN_CTX_get(ctx);
 	n3 = BN_CTX_get(ctx);
 	if (n3 == NULL) goto err;
 
 	/* Note that in this function we must not read components of 'a'
 	 * once we have written the corresponding components of 'r'.
 	 * ('r' might the same as 'a'.)
 	 */
 
 	/* n1 */
 	if (a->Z_is_one)
 		{
 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
 		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
 		/* n1 = 3 * X_a^2 + a_curve */
 		}
 	else if (group->a_is_minus3)
 		{
 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
 		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
 		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
 		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
 		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
 		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
 		 *    = 3 * X_a^2 - 3 * Z_a^4 */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
 		if (!field_sqr(group, n1, n1, ctx)) goto err;
 		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
 		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
 		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
 		}
 
 	/* Z_r */
 	if (a->Z_is_one)
 		{
 		if (!BN_copy(n0, &a->Y)) goto err;
 		}
 	else
 		{
 		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
 		}
 	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
 	r->Z_is_one = 0;
 	/* Z_r = 2 * Y_a * Z_a */
 
 	/* n2 */
 	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
 	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
 	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
 	/* n2 = 4 * X_a * Y_a^2 */
 
 	/* X_r */
 	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
 	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
 	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
 	/* X_r = n1^2 - 2 * n2 */
 	
 	/* n3 */
 	if (!field_sqr(group, n0, n3, ctx)) goto err;
 	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
 	/* n3 = 8 * Y_a^4 */
 	
 	/* Y_r */
 	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
 	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
 	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
 	/* Y_r = n1 * (n2 - X_r) - n3 */
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
 		/* point is its own inverse */
 		return 1;
 	
 	return BN_usub(&point->Y, &group->field, &point->Y);
 	}
 
 
 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	return BN_is_zero(&point->Z);
 	}
 
 
 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *rh, *tmp, *Z4, *Z6;
 	int ret = -1;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		return 1;
 	
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	rh = BN_CTX_get(ctx);
 	tmp = BN_CTX_get(ctx);
 	Z4 = BN_CTX_get(ctx);
 	Z6 = BN_CTX_get(ctx);
 	if (Z6 == NULL) goto err;
 
 	/* We have a curve defined by a Weierstrass equation
 	 *      y^2 = x^3 + a*x + b.
 	 * The point to consider is given in Jacobian projective coordinates
 	 * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
 	 * Substituting this and multiplying by  Z^6  transforms the above equation into
 	 *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
 	 * To test this, we add up the right-hand side in 'rh'.
 	 */
 
 	/* rh := X^2 */
 	if (!field_sqr(group, rh, &point->X, ctx)) goto err;
 
 	if (!point->Z_is_one)
 		{
 		if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
 		if (!field_sqr(group, Z4, tmp, ctx)) goto err;
 		if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
 
 		/* rh := (rh + a*Z^4)*X */
 		if (group->a_is_minus3)
 			{
 			if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
 			if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
 			if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 			}
 		else
 			{
 			if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
 			if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 			}
 
 		/* rh := rh + b*Z^6 */
 		if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
 		if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
 		}
 	else
 		{
 		/* point->Z_is_one */
 
 		/* rh := (rh + a)*X */
 		if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
 		if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 		/* rh := rh + b */
 		if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
 		}
 
 	/* 'lh' := Y^2 */
 	if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
 
 	ret = (0 == BN_ucmp(tmp, rh));
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	/* return values:
 	 *  -1   error
 	 *   0   equal (in affine coordinates)
 	 *   1   not equal
 	 */
 
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
 	const BIGNUM *tmp1_, *tmp2_;
 	int ret = -1;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		return 1;
 	
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
 		}
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	tmp1 = BN_CTX_get(ctx);
 	tmp2 = BN_CTX_get(ctx);
 	Za23 = BN_CTX_get(ctx);
 	Zb23 = BN_CTX_get(ctx);
 	if (Zb23 == NULL) goto end;
 
 	/* We have to decide whether
 	 *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
 	 * or equivalently, whether
 	 *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
 	 */
 
 	if (!b->Z_is_one)
 		{
 		if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
 		if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
 		tmp1_ = tmp1;
 		}
 	else
 		tmp1_ = &a->X;
 	if (!a->Z_is_one)
 		{
 		if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
 		if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
 		tmp2_ = tmp2;
 		}
 	else
 		tmp2_ = &b->X;
 	
 	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
 	if (BN_cmp(tmp1_, tmp2_) != 0)
 		{
 		ret = 1; /* points differ */
 		goto end;
 		}
 
 
 	if (!b->Z_is_one)
 		{
 		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
 		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
 		/* tmp1_ = tmp1 */
 		}
 	else
 		tmp1_ = &a->Y;
 	if (!a->Z_is_one)
 		{
 		if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
 		if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
 		/* tmp2_ = tmp2 */
 		}
 	else
 		tmp2_ = &b->Y;
 
 	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
 	if (BN_cmp(tmp1_, tmp2_) != 0)
 		{
 		ret = 1; /* points differ */
 		goto end;
 		}
 
 	/* points are equal */
 	ret = 0;
 
  end:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	int ret = 0;
 
 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
 		return 1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 	if (!point->Z_is_one)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 	
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp, *tmp_Z;
 	BIGNUM **prod_Z = NULL;
 	size_t i;
 	int ret = 0;
 
 	if (num == 0)
 		return 1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	tmp = BN_CTX_get(ctx);
 	tmp_Z = BN_CTX_get(ctx);
 	if (tmp == NULL || tmp_Z == NULL) goto err;
 
 	prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]);
 	if (prod_Z == NULL) goto err;
 	for (i = 0; i < num; i++)
 		{
 		prod_Z[i] = BN_new();
 		if (prod_Z[i] == NULL) goto err;
 		}
 
 	/* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
 	 * skipping any zero-valued inputs (pretend that they're 1). */
 
 	if (!BN_is_zero(&points[0]->Z))
 		{
 		if (!BN_copy(prod_Z[0], &points[0]->Z)) goto err;
 		}
 	else
 		{
 		if (group->meth->field_set_to_one != 0)
 			{
 			if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_one(prod_Z[0])) goto err;
 			}
 		}
 
 	for (i = 1; i < num; i++)
 		{
 		if (!BN_is_zero(&points[i]->Z))
 			{
 			if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_copy(prod_Z[i], prod_Z[i - 1])) goto err;
 			}
 		}
 
 	/* Now use a single explicit inversion to replace every
 	 * non-zero points[i]->Z by its inverse. */
 
 	if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
 		goto err;
 		}
 	if (group->meth->field_encode != 0)
 		{
 		/* In the Montgomery case, we just turned  R*H  (representing H)
 		 * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
 		 * i.e. we need to multiply by the Montgomery factor twice. */
 		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
 		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
 		}
 
 	for (i = num - 1; i > 0; --i)
 		{
 		/* Loop invariant: tmp is the product of the inverses of
 		 * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
 		if (!BN_is_zero(&points[i]->Z))
 			{
 			/* Set tmp_Z to the inverse of points[i]->Z (as product
 			 * of Z inverses 0 .. i, Z values 0 .. i - 1). */
 			if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) goto err;
 			/* Update tmp to satisfy the loop invariant for i - 1. */
 			if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) goto err;
 			/* Replace points[i]->Z by its inverse. */
 			if (!BN_copy(&points[i]->Z, tmp_Z)) goto err;
 			}
 		}
 
 	if (!BN_is_zero(&points[0]->Z))
 		{
 		/* Replace points[0]->Z by its inverse. */
 		if (!BN_copy(&points[0]->Z, tmp)) goto err;
 		}
 
 	/* Finally, fix up the X and Y coordinates for all points. */
 
 	for (i = 0; i < num; i++)
 		{
 		EC_POINT *p = points[i];
 
 		if (!BN_is_zero(&p->Z))
 			{
 			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
 
 			if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) goto err;
 			if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) goto err;
 
 			if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) goto err;
 			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) goto err;
 
 			if (group->meth->field_set_to_one != 0)
 				{
 				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
 				}
 			else
 				{
 				if (!BN_one(&p->Z)) goto err;
 				}
 			p->Z_is_one = 1;
 			}
 		}
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	if (prod_Z != NULL)
 		{
 		for (i = 0; i < num; i++)
 			{
 			if (prod_Z[i] == NULL) break;
 			BN_clear_free(prod_Z[i]);
 			}
 		OPENSSL_free(prod_Z);
 		}
 	return ret;
 	}
 
 
 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_mod_mul(r, a, b, &group->field, ctx);
 	}
 
 
 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
 	{
 	return BN_mod_sqr(r, a, &group->field, ctx);
 	}
Index: releng/8.4/crypto/openssl/crypto/ec/ectest.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/ec/ectest.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/ec/ectest.c	(revision 284295)
@@ -1,1344 +1,1344 @@
 /* crypto/ec/ectest.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * The elliptic curve binary polynomial software is originally written by 
  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 
 #include 
 #include 
 #ifdef FLAT_INC
 #include "e_os.h"
 #else
 #include "../e_os.h"
 #endif
 #include 
 #include 
 
 
 #ifdef OPENSSL_NO_EC
 int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
 #else
 
 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include 
 #include 
 #include 
 #include 
 #include 
 
 #if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
 /* suppress "too big too optimize" warning */
 #pragma warning(disable:4959)
 #endif
 
 #define ABORT do { \
 	fflush(stdout); \
 	fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
 	ERR_print_errors_fp(stderr); \
 	EXIT(1); \
 } while (0)
 
 void prime_field_tests(void);
 void char2_field_tests(void);
 void internal_curve_test(void);
 
 #define TIMING_BASE_PT 0
 #define TIMING_RAND_PT 1
 #define TIMING_SIMUL 2
 
 #if 0
 static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
 	{
 	clock_t clck;
 	int i, j;
 	BIGNUM *s;
 	BIGNUM *r[10], *r0[10];
 	EC_POINT *P;
 		
 	s = BN_new();
 	if (s == NULL) ABORT;
 
 	fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
 	if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
 	fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
 	fflush(stdout);
 
 	P = EC_POINT_new(group);
 	if (P == NULL) ABORT;
 	EC_POINT_copy(P, EC_GROUP_get0_generator(group));
 
 	for (i = 0; i < 10; i++)
 		{
 		if ((r[i] = BN_new()) == NULL) ABORT;
 		if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
 		if (type != TIMING_BASE_PT)
 			{
 			if ((r0[i] = BN_new()) == NULL) ABORT;
 			if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
 			}
 		}
 
 	clck = clock();
 	for (i = 0; i < 10; i++)
 		{
 		for (j = 0; j < 10; j++)
 			{
 			if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, 
 				(type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
 			}
 		}
 	clck = clock() - clck;
 
 	fprintf(stdout, "\n");
 
 #ifdef CLOCKS_PER_SEC
 	/* "To determine the time in seconds, the value returned
 	 * by the clock function should be divided by the value
 	 * of the macro CLOCKS_PER_SEC."
 	 *                                       -- ISO/IEC 9899 */
 #	define UNIT "s"
 #else
 	/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
 	 *                            -- cc on NeXTstep/OpenStep */
 #	define UNIT "units"
 #	define CLOCKS_PER_SEC 1
 #endif
 
 	if (type == TIMING_BASE_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"base point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_RAND_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"random point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_SIMUL) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
 	}
 	fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
 
 	EC_POINT_free(P);
 	BN_free(s);
 	for (i = 0; i < 10; i++)
 		{
 		BN_free(r[i]);
 		if (type != TIMING_BASE_PT) BN_free(r0[i]);
 		}
 	}
 #endif
 
 void prime_field_tests()
 	{	
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "17")) ABORT;
 	if (!BN_hex2bn(&a, "1")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
 	                                             * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	if (!x || !y || !z) ABORT;
 
 	if (!BN_hex2bn(&x, "D")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 
 #if 0 /* optional */
 		{
 			EC_POINT *points[3];
 		
 			points[0] = R;
 			points[1] = Q;
 			points[2] = P;
 			if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
 		}
 #endif
 
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octect string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octect string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
 	fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, ", Y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, ", Z = 0x");
 	BN_print_fp(stdout, z);
 	fprintf(stdout, "\n");
 
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
 	 * -- not a NIST curve, but commonly used */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
 	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 160) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_160, group)) ABORT;
 
 
 	/* Curve P-192 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-192 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 192) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_192, group)) ABORT;
 
 
 	/* Curve P-224 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
 	if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-224 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 224) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_224, group)) ABORT;
 
 
 	/* Curve P-256 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
 		"84F3B9CAC2FC632551")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-256 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 256) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_256, group)) ABORT;
 
 
 	/* Curve P-384 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
 		"120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
 		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-384 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"
 		"7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 384) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_384, group)) ABORT;
 
 
 	/* Curve P-521 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"
 		"315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"
 		"DF883D2C34F1EF451FD46B503F00")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"
 		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
 		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
 		"C9B8899C47AEBB6FB71E91386409")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-521 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"
 		"B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"
 		"7086A272C24088BE94769FD16650")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 521) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_521, group)) ABORT;
 
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[4];
 		const BIGNUM *scalars[4];
 		BIGNUM scalar3;
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 		points[3] = Q;
 
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		BN_init(&scalar3);
 		BN_zero(&scalar3);
 		scalars[3] = &scalar3;
 
 		if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 
 		BN_free(&scalar3);
 	}
 
 
 #if 0
 	timings(P_160, TIMING_BASE_PT, ctx);
 	timings(P_160, TIMING_RAND_PT, ctx);
 	timings(P_160, TIMING_SIMUL, ctx);
 	timings(P_192, TIMING_BASE_PT, ctx);
 	timings(P_192, TIMING_RAND_PT, ctx);
 	timings(P_192, TIMING_SIMUL, ctx);
 	timings(P_224, TIMING_BASE_PT, ctx);
 	timings(P_224, TIMING_RAND_PT, ctx);
 	timings(P_224, TIMING_SIMUL, ctx);
 	timings(P_256, TIMING_BASE_PT, ctx);
 	timings(P_256, TIMING_RAND_PT, ctx);
 	timings(P_256, TIMING_SIMUL, ctx);
 	timings(P_384, TIMING_BASE_PT, ctx);
 	timings(P_384, TIMING_RAND_PT, ctx);
 	timings(P_384, TIMING_SIMUL, ctx);
 	timings(P_521, TIMING_BASE_PT, ctx);
 	timings(P_521, TIMING_RAND_PT, ctx);
 	timings(P_521, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z);
 
 	if (P_160) EC_GROUP_free(P_160);
 	if (P_192) EC_GROUP_free(P_192);
 	if (P_224) EC_GROUP_free(P_224);
 	if (P_256) EC_GROUP_free(P_256);
 	if (P_384) EC_GROUP_free(P_384);
 	if (P_521) EC_GROUP_free(P_521);
 
 	}
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n"); \
 	/* G_y value taken from the standard: */ \
 	if (!BN_hex2bn(&z, _y)) ABORT; \
 	if (0 != BN_cmp(y, z)) ABORT;
 #else 
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!BN_hex2bn(&y, _y)) ABORT; \
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n");
 #endif
 
 #define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&p, _p)) ABORT; \
 	if (!BN_hex2bn(&a, _a)) ABORT; \
 	if (!BN_hex2bn(&b, _b)) ABORT; \
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \
 	CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	fprintf(stdout, "verify degree ..."); \
 	if (EC_GROUP_get_degree(group) != _degree) ABORT; \
 	fprintf(stdout, " ok\n"); \
 	fprintf(stdout, "verify group order ..."); \
 	fflush(stdout); \
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT; \
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
 	fprintf(stdout, "."); \
 	fflush(stdout); \
 	/* if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; */ \
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
 	fprintf(stdout, " ok\n"); \
 	if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
 	if (!EC_GROUP_copy(_variable, group)) ABORT;
 
 void char2_field_tests()
 	{	
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
 	EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z, *cof;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "13")) ABORT;
 	if (!BN_hex2bn(&a, "3")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
 	                                                * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n(0x... means binary polynomial)\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	cof = BN_new();
 	if (!x || !y || !z || !cof) ABORT;
 
 	if (!BN_hex2bn(&x, "6")) ABORT;
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
 #else
 	if (!BN_hex2bn(&y, "8")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 
 	fprintf(stdout, "\n");
 	
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve K-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"1",
 		"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
 		"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
 		1,
 		"04000000000000000000020108A2E0CC0D99F8A5EF",
 		"2",
 		163,
 		C2_K163
 		);
 
 	/* Curve B-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"020A601907B8C953CA1481EB10512F78744A3205FD",
 		"03F0EBA16286A2D57EA0991168D4994637E8343E36",
 		"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
 		1,
 		"040000000000000000000292FE77E70C12A4234C33",
 		"2",
 		163,
 		C2_B163
 		);
 
 	/* Curve K-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"0",
 		"1",
 		"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
 		"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
 		0,
 		"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
 		"4",
 		233,
 		C2_K233
 		);
 
 	/* Curve B-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"000000000000000000000000000000000000000000000000000000000001",
 		"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
 		"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
 		"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
 		1,
 		"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
 		"2",
 		233,
 		C2_B233
 		);
 
 	/* Curve K-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"0",
 		"1",
 		"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
 		"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
 		0,
 		"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
 		"4",
 		283,
 		C2_K283
 		);
 
 	/* Curve B-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"000000000000000000000000000000000000000000000000000000000000000000000001",
 		"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
 		"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
 		"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
 		"2",
 		283,
 		C2_B283
 		);
 
 	/* Curve K-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"0",
 		"1",
 		"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
 		"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
 		1,
 		"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
 		"4",
 		409,
 		C2_K409
 		);
 
 	/* Curve B-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
 		"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
 		"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
 		1,
 		"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
 		"2",
 		409,
 		C2_B409
 		);
 
 	/* Curve K-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"0",
 		"1",
 		"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
 		"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
 		0,
 		"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
 		"4",
 		571,
 		C2_K571
 		);
 
 	/* Curve B-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
 		"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
 		"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
 		"2",
 		571,
 		C2_B571
 		);
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[3];
 		const BIGNUM *scalars[3];
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 	}
 
 
 #if 0
 	timings(C2_K163, TIMING_BASE_PT, ctx);
 	timings(C2_K163, TIMING_RAND_PT, ctx);
 	timings(C2_K163, TIMING_SIMUL, ctx);
 	timings(C2_B163, TIMING_BASE_PT, ctx);
 	timings(C2_B163, TIMING_RAND_PT, ctx);
 	timings(C2_B163, TIMING_SIMUL, ctx);
 	timings(C2_K233, TIMING_BASE_PT, ctx);
 	timings(C2_K233, TIMING_RAND_PT, ctx);
 	timings(C2_K233, TIMING_SIMUL, ctx);
 	timings(C2_B233, TIMING_BASE_PT, ctx);
 	timings(C2_B233, TIMING_RAND_PT, ctx);
 	timings(C2_B233, TIMING_SIMUL, ctx);
 	timings(C2_K283, TIMING_BASE_PT, ctx);
 	timings(C2_K283, TIMING_RAND_PT, ctx);
 	timings(C2_K283, TIMING_SIMUL, ctx);
 	timings(C2_B283, TIMING_BASE_PT, ctx);
 	timings(C2_B283, TIMING_RAND_PT, ctx);
 	timings(C2_B283, TIMING_SIMUL, ctx);
 	timings(C2_K409, TIMING_BASE_PT, ctx);
 	timings(C2_K409, TIMING_RAND_PT, ctx);
 	timings(C2_K409, TIMING_SIMUL, ctx);
 	timings(C2_B409, TIMING_BASE_PT, ctx);
 	timings(C2_B409, TIMING_RAND_PT, ctx);
 	timings(C2_B409, TIMING_SIMUL, ctx);
 	timings(C2_K571, TIMING_BASE_PT, ctx);
 	timings(C2_K571, TIMING_RAND_PT, ctx);
 	timings(C2_K571, TIMING_SIMUL, ctx);
 	timings(C2_B571, TIMING_BASE_PT, ctx);
 	timings(C2_B571, TIMING_RAND_PT, ctx);
 	timings(C2_B571, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z); BN_free(cof);
 
 	if (C2_K163) EC_GROUP_free(C2_K163);
 	if (C2_B163) EC_GROUP_free(C2_B163);
 	if (C2_K233) EC_GROUP_free(C2_K233);
 	if (C2_B233) EC_GROUP_free(C2_B233);
 	if (C2_K283) EC_GROUP_free(C2_K283);
 	if (C2_B283) EC_GROUP_free(C2_B283);
 	if (C2_K409) EC_GROUP_free(C2_K409);
 	if (C2_B409) EC_GROUP_free(C2_B409);
 	if (C2_K571) EC_GROUP_free(C2_K571);
 	if (C2_B571) EC_GROUP_free(C2_B571);
 
 	}
 
 void internal_curve_test(void)
 	{
 	EC_builtin_curve *curves = NULL;
 	size_t crv_len = 0, n = 0;
 	int    ok = 1;
 
 	crv_len = EC_get_builtin_curves(NULL, 0);
 
 	curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
 
 	if (curves == NULL)
 		return;
 
 	if (!EC_get_builtin_curves(curves, crv_len))
 		{
 		OPENSSL_free(curves);
 		return;
 		}
 
 	fprintf(stdout, "testing internal curves: ");
 		
 	for (n = 0; n < crv_len; n++)
 		{
 		EC_GROUP *group = NULL;
 		int nid = curves[n].nid;
 		if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			/* try next curve */
 			continue;
 			}
 		if (!EC_GROUP_check(group, NULL))
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_check() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			EC_GROUP_free(group);
 			/* try the next curve */
 			continue;
 			}
 		fprintf(stdout, ".");
 		fflush(stdout);
 		EC_GROUP_free(group);
 		}
 	if (ok)
 		fprintf(stdout, " ok\n");
 	else
 		fprintf(stdout, " failed\n");
 	OPENSSL_free(curves);
 	return;
 	}
 
 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
 
 int main(int argc, char *argv[])
 	{	
 	
 	/* enable memory leak checking unless explicitly disabled */
 	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
 		{
 		CRYPTO_malloc_debug_init();
 		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
 		}
 	else
 		{
 		/* OPENSSL_DEBUG_MEMORY=off */
 		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
 		}
 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 	ERR_load_crypto_strings();
 
 	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
 
 	prime_field_tests();
 	puts("");
 	char2_field_tests();
 	/* test the internal curves */
 	internal_curve_test();
 
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_cleanup();
 #endif
 	CRYPTO_cleanup_all_ex_data();
 	ERR_free_strings();
 	ERR_remove_state(0);
 	CRYPTO_mem_leaks_fp(stderr);
 	
 	return 0;
 	}
 #endif
Index: releng/8.4/crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/objects/obj_dat.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/objects/obj_dat.c	(revision 284295)
@@ -1,791 +1,794 @@
 /* crypto/objects/obj_dat.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 
 /* obj_dat.h is generated from objects.h by obj_dat.pl */
 #ifndef OPENSSL_NO_OBJECT
 #include "obj_dat.h"
 #else
 /* You will have to load all the objects needed manually in the application */
 #define NUM_NID 0
 #define NUM_SN 0
 #define NUM_LN 0
 #define NUM_OBJ 0
 static unsigned char lvalues[1];
 static ASN1_OBJECT nid_objs[1];
 static ASN1_OBJECT *sn_objs[1];
 static ASN1_OBJECT *ln_objs[1];
 static ASN1_OBJECT *obj_objs[1];
 #endif
 
 static int sn_cmp(const void *a, const void *b);
 static int ln_cmp(const void *a, const void *b);
 static int obj_cmp(const void *a, const void *b);
 #define ADDED_DATA	0
 #define ADDED_SNAME	1
 #define ADDED_LNAME	2
 #define ADDED_NID	3
 
 typedef struct added_obj_st
 	{
 	int type;
 	ASN1_OBJECT *obj;
 	} ADDED_OBJ;
 
 static int new_nid=NUM_NID;
 static LHASH *added=NULL;
 
 static int sn_cmp(const void *a, const void *b)
 	{
 	const ASN1_OBJECT * const *ap = a, * const *bp = b;
 	return(strcmp((*ap)->sn,(*bp)->sn));
 	}
 
 static int ln_cmp(const void *a, const void *b)
 	{ 
 	const ASN1_OBJECT * const *ap = a, * const *bp = b;
 	return(strcmp((*ap)->ln,(*bp)->ln));
 	}
 
 /* static unsigned long add_hash(ADDED_OBJ *ca) */
 static unsigned long add_hash(const void *ca_void)
 	{
 	const ASN1_OBJECT *a;
 	int i;
 	unsigned long ret=0;
 	unsigned char *p;
 	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
 
 	a=ca->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		ret=a->length<<20L;
 		p=(unsigned char *)a->data;
 		for (i=0; ilength; i++)
 			ret^=p[i]<<((i*3)%24);
 		break;
 	case ADDED_SNAME:
 		ret=lh_strhash(a->sn);
 		break;
 	case ADDED_LNAME:
 		ret=lh_strhash(a->ln);
 		break;
 	case ADDED_NID:
 		ret=a->nid;
 		break;
 	default:
 		/* abort(); */
 		return 0;
 		}
 	ret&=0x3fffffffL;
 	ret|=ca->type<<30L;
 	return(ret);
 	}
 
 /* static int add_cmp(ADDED_OBJ *ca, ADDED_OBJ *cb) */
 static int add_cmp(const void *ca_void, const void *cb_void)
 	{
 	ASN1_OBJECT *a,*b;
 	int i;
 	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
 	const ADDED_OBJ *cb = (const ADDED_OBJ *)cb_void;
 
 	i=ca->type-cb->type;
 	if (i) return(i);
 	a=ca->obj;
 	b=cb->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		i=(a->length - b->length);
 		if (i) return(i);
 		return(memcmp(a->data,b->data,(size_t)a->length));
 	case ADDED_SNAME:
 		if (a->sn == NULL) return(-1);
 		else if (b->sn == NULL) return(1);
 		else return(strcmp(a->sn,b->sn));
 	case ADDED_LNAME:
 		if (a->ln == NULL) return(-1);
 		else if (b->ln == NULL) return(1);
 		else return(strcmp(a->ln,b->ln));
 	case ADDED_NID:
 		return(a->nid-b->nid);
 	default:
 		/* abort(); */
 		return 0;
 		}
 	}
 
 static int init_added(void)
 	{
 	if (added != NULL) return(1);
 	added=lh_new(add_hash,add_cmp);
 	return(added != NULL);
 	}
 
 static void cleanup1(ADDED_OBJ *a)
 	{
 	a->obj->nid=0;
 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
 	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	}
 
 static void cleanup2(ADDED_OBJ *a)
 	{ a->obj->nid++; }
 
 static void cleanup3(ADDED_OBJ *a)
 	{
 	if (--a->obj->nid == 0)
 		ASN1_OBJECT_free(a->obj);
 	OPENSSL_free(a);
 	}
 
 static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *)
 
 void OBJ_cleanup(void)
 	{
 	if (added == NULL) return;
 	added->down_load=0;
 	lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
 	lh_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
 	lh_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
 	lh_free(added);
 	added=NULL;
 	}
 
 int OBJ_new_nid(int num)
 	{
 	int i;
 
 	i=new_nid;
 	new_nid+=num;
 	return(i);
 	}
 
 int OBJ_add_object(const ASN1_OBJECT *obj)
 	{
 	ASN1_OBJECT *o;
 	ADDED_OBJ *ao[4]={NULL,NULL,NULL,NULL},*aop;
 	int i;
 
 	if (added == NULL)
 		if (!init_added()) return(0);
 	if ((o=OBJ_dup(obj)) == NULL) goto err;
 	if (!(ao[ADDED_NID]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if ((o->length != 0) && (obj->data != NULL))
 		if (!(ao[ADDED_DATA]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->sn != NULL)
 		if (!(ao[ADDED_SNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->ln != NULL)
 		if (!(ao[ADDED_LNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		{
 		if (ao[i] != NULL)
 			{
 			ao[i]->type=i;
 			ao[i]->obj=o;
 			aop=(ADDED_OBJ *)lh_insert(added,ao[i]);
 			/* memory leak, buit should not normally matter */
 			if (aop != NULL)
 				OPENSSL_free(aop);
 			}
 		}
 	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA);
 
 	return(o->nid);
 err2:
 	OBJerr(OBJ_F_OBJ_ADD_OBJECT,ERR_R_MALLOC_FAILURE);
 err:
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		if (ao[i] != NULL) OPENSSL_free(ao[i]);
 	if (o != NULL) OPENSSL_free(o);
 	return(NID_undef);
 	}
 
 ASN1_OBJECT *OBJ_nid2obj(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return((ASN1_OBJECT *)&(nid_objs[n]));
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2sn(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].sn);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->sn);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2ln(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].ln);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->ln);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 int OBJ_obj2nid(const ASN1_OBJECT *a)
 	{
 	ASN1_OBJECT **op;
 	ADDED_OBJ ad,*adp;
 
 	if (a == NULL)
 		return(NID_undef);
 	if (a->nid != 0)
 		return(a->nid);
 
+	if (a->length == 0)
+	    return NID_undef;
+
 	if (added != NULL)
 		{
 		ad.type=ADDED_DATA;
 		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((const char *)&a,(const char *)obj_objs,
 		NUM_OBJ, sizeof(ASN1_OBJECT *),obj_cmp);
 	if (op == NULL)
 		return(NID_undef);
 	return((*op)->nid);
 	}
 
 /* Convert an object name into an ASN1_OBJECT
  * if "noname" is not set then search for short and long names first.
  * This will convert the "dotted" form into an object: unlike OBJ_txt2nid
  * it can be used with any objects, not just registered ones.
  */
 
 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
 	{
 	int nid = NID_undef;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	unsigned char *p;
 	const unsigned char *cp;
 	int i, j;
 
 	if(!no_name) {
 		if( ((nid = OBJ_sn2nid(s)) != NID_undef) ||
 			((nid = OBJ_ln2nid(s)) != NID_undef) ) 
 					return OBJ_nid2obj(nid);
 	}
 
 	/* Work out size of content octets */
 	i=a2d_ASN1_OBJECT(NULL,0,s,-1);
 	if (i <= 0) {
 		/* Don't clear the error */
 		/*ERR_clear_error();*/
 		return NULL;
 	}
 	/* Work out total size */
 	j = ASN1_object_size(0,i,V_ASN1_OBJECT);
 
 	if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL;
 
 	p = buf;
 	/* Write out tag+length */
 	ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
 	/* Write out contents */
 	a2d_ASN1_OBJECT(p,i,s,-1);
 
 	cp=buf;
 	op=d2i_ASN1_OBJECT(NULL,&cp,j);
 	OPENSSL_free(buf);
 	return op;
 	}
 
 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
 {
 	int i,n=0,len,nid, first, use_bn;
 	BIGNUM *bl;
 	unsigned long l;
 	unsigned char *p;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
 	/* Ensure that, at every state, |buf| is NUL-terminated. */
 	if (buf && buf_len > 0)
 		buf[0] = '\0';
 
 	if ((a == NULL) || (a->data == NULL))
 		return(0);
 
 	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
 		{
 		const char *s;
 		s=OBJ_nid2ln(nid);
 		if (s == NULL)
 			s=OBJ_nid2sn(nid);
 		if (s)
 			{
 			if (buf)
 				BUF_strlcpy(buf,s,buf_len);
 			n=strlen(s);
 			return n;
 			}
 		}
 
 
 	len=a->length;
 	p=a->data;
 
 	first = 1;
 	bl = NULL;
 
 	while (len > 0)
 		{
 		l=0;
 		use_bn = 0;
 		for (;;)
 			{
 			unsigned char c = *p++;
 			len--;
 			if ((len == 0) && (c & 0x80))
 				goto err;
 			if (use_bn)
 				{
 				if (!BN_add_word(bl, c & 0x7f))
 					goto err;
 				}
 			else
 				l |= c  & 0x7f;
 			if (!(c & 0x80))
 				break;
 			if (!use_bn && (l > (ULONG_MAX >> 7L)))
 				{
 				if (!bl && !(bl = BN_new()))
 					goto err;
 				if (!BN_set_word(bl, l))
 					goto err;
 				use_bn = 1;
 				}
 			if (use_bn)
 				{
 				if (!BN_lshift(bl, bl, 7))
 					goto err;
 				}
 			else
 				l<<=7L;
 			}
 
 		if (first)
 			{
 			first = 0;
 			if (l >= 80)
 				{
 				i = 2;
 				if (use_bn)
 					{
 					if (!BN_sub_word(bl, 80))
 						goto err;
 					}
 				else
 					l -= 80;
 				}
 			else
 				{
 				i=(int)(l/40);
 				l-=(long)(i*40);
 				}
 			if (buf && (buf_len > 1))
 				{
 				*buf++ = i + '0';
 				*buf = '\0';
 				buf_len--;
 				}
 			n++;
 			}
 
 		if (use_bn)
 			{
 			char *bndec;
 			bndec = BN_bn2dec(bl);
 			if (!bndec)
 				goto err;
 			i = strlen(bndec);
 			if (buf)
 				{
 				if (buf_len > 1)
 					{
 					*buf++ = '.';
 					*buf = '\0';
 					buf_len--;
 					}
 				BUF_strlcpy(buf,bndec,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n++;
 			n += i;
 			OPENSSL_free(bndec);
 			}
 		else
 			{
 			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
 			i=strlen(tbuf);
 			if (buf && (buf_len > 0))
 				{
 				BUF_strlcpy(buf,tbuf,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n+=i;
 			l=0;
 			}
 		}
 
 	if (bl)
 		BN_free(bl);
 	return n;
 
 	err:
 	if (bl)
 		BN_free(bl);
 	return -1;
 }
 
 int OBJ_txt2nid(const char *s)
 {
 	ASN1_OBJECT *obj;
 	int nid;
 	obj = OBJ_txt2obj(s, 0);
 	nid = OBJ_obj2nid(obj);
 	ASN1_OBJECT_free(obj);
 	return nid;
 }
 
 int OBJ_ln2nid(const char *s)
 	{
 	ASN1_OBJECT o,*oo= &o,**op;
 	ADDED_OBJ ad,*adp;
 
 	o.ln=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_LNAME;
 		ad.obj= &o;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs, NUM_LN,
 		sizeof(ASN1_OBJECT *),ln_cmp);
 	if (op == NULL) return(NID_undef);
 	return((*op)->nid);
 	}
 
 int OBJ_sn2nid(const char *s)
 	{
 	ASN1_OBJECT o,*oo= &o,**op;
 	ADDED_OBJ ad,*adp;
 
 	o.sn=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_SNAME;
 		ad.obj= &o;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN,
 		sizeof(ASN1_OBJECT *),sn_cmp);
 	if (op == NULL) return(NID_undef);
 	return((*op)->nid);
 	}
 
 static int obj_cmp(const void *ap, const void *bp)
 	{
 	int j;
 	const ASN1_OBJECT *a= *(ASN1_OBJECT * const *)ap;
 	const ASN1_OBJECT *b= *(ASN1_OBJECT * const *)bp;
 
 	j=(a->length - b->length);
         if (j) return(j);
 	return(memcmp(a->data,b->data,a->length));
         }
 
 const char *OBJ_bsearch(const char *key, const char *base, int num, int size,
 	int (*cmp)(const void *, const void *))
 	{
 	return OBJ_bsearch_ex(key, base, num, size, cmp, 0);
 	}
 
 const char *OBJ_bsearch_ex(const char *key, const char *base, int num,
 	int size, int (*cmp)(const void *, const void *), int flags)
 	{
 	int l,h,i=0,c=0;
 	const char *p = NULL;
 
 	if (num == 0) return(NULL);
 	l=0;
 	h=num;
 	while (l < h)
 		{
 		i=(l+h)/2;
 		p= &(base[i*size]);
 		c=(*cmp)(key,p);
 		if (c < 0)
 			h=i;
 		else if (c > 0)
 			l=i+1;
 		else
 			break;
 		}
 #ifdef CHARSET_EBCDIC
 /* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and
  * I don't have perl (yet), we revert to a *LINEAR* search
  * when the object wasn't found in the binary search.
  */
 	if (c != 0)
 		{
 		for (i=0; i 0 && (*cmp)(key,&(base[(i-1)*size])) == 0)
 			i--;
 		p = &(base[i*size]);
 		}
 	return(p);
 	}
 
 int OBJ_create_objects(BIO *in)
 	{
 	MS_STATIC char buf[512];
 	int i,num=0;
 	char *o,*s,*l=NULL;
 
 	for (;;)
 		{
 		s=o=NULL;
 		i=BIO_gets(in,buf,512);
 		if (i <= 0) return(num);
 		buf[i-1]='\0';
 		if (!isalnum((unsigned char)buf[0])) return(num);
 		o=s=buf;
 		while (isdigit((unsigned char)*s) || (*s == '.'))
 			s++;
 		if (*s != '\0')
 			{
 			*(s++)='\0';
 			while (isspace((unsigned char)*s))
 				s++;
 			if (*s == '\0')
 				s=NULL;
 			else
 				{
 				l=s;
 				while ((*l != '\0') && !isspace((unsigned char)*l))
 					l++;
 				if (*l != '\0')
 					{
 					*(l++)='\0';
 					while (isspace((unsigned char)*l))
 						l++;
 					if (*l == '\0') l=NULL;
 					}
 				else
 					l=NULL;
 				}
 			}
 		else
 			s=NULL;
 		if ((o == NULL) || (*o == '\0')) return(num);
 		if (!OBJ_create(o,s,l)) return(num);
 		num++;
 		}
 	/* return(num); */
 	}
 
 int OBJ_create(const char *oid, const char *sn, const char *ln)
 	{
 	int ok=0;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	int i;
 
 	i=a2d_ASN1_OBJECT(NULL,0,oid,-1);
 	if (i <= 0) return(0);
 
 	if ((buf=(unsigned char *)OPENSSL_malloc(i)) == NULL)
 		{
 		OBJerr(OBJ_F_OBJ_CREATE,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	i=a2d_ASN1_OBJECT(buf,i,oid,-1);
 	if (i == 0)
 		goto err;
 	op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln);
 	if (op == NULL) 
 		goto err;
 	ok=OBJ_add_object(op);
 err:
 	ASN1_OBJECT_free(op);
 	OPENSSL_free(buf);
 	return(ok);
 	}
Index: releng/8.4/crypto/openssl/crypto/pkcs7/pk7_doit.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284295)
@@ -1,1233 +1,1236 @@
 /* crypto/pkcs7/pk7_doit.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value);
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
 
 static int PKCS7_type_is_other(PKCS7* p7)
 	{
 	int isOther=1;
 	
 	int nid=OBJ_obj2nid(p7->type);
 
 	switch( nid )
 		{
 	case NID_pkcs7_data:
 	case NID_pkcs7_signed:
 	case NID_pkcs7_enveloped:
 	case NID_pkcs7_signedAndEnveloped:
 	case NID_pkcs7_digest:
 	case NID_pkcs7_encrypted:
 		isOther=0;
 		break;
 	default:
 		isOther=1;
 		}
 
 	return isOther;
 
 	}
 
 static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
 	{
 	if ( PKCS7_type_is_data(p7))
 		return p7->d.data;
 	if ( PKCS7_type_is_other(p7) && p7->d.other
 		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
 		return p7->d.other->value.octet_string;
 	return NULL;
 	}
 
 static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
 	{
 	BIO *btmp;
 	const EVP_MD *md;
 	if ((btmp=BIO_new(BIO_f_md())) == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 
 	md=EVP_get_digestbyobj(alg->algorithm);
 	if (md == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 		goto err;
 		}
 
 	BIO_set_md(btmp,md);
 	if (*pbio == NULL)
 		*pbio=btmp;
 	else if (!BIO_push(*pbio,btmp))
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 	btmp=NULL;
 
 	return 1;
 
 	err:
 	if (btmp)
 		BIO_free(btmp);
 	return 0;
 
 	}
 
 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
 	{
 	int i;
 	BIO *out=NULL,*btmp=NULL;
 	X509_ALGOR *xa = NULL;
 	const EVP_CIPHER *evp_cipher=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	X509_ALGOR *xalg=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
 	EVP_PKEY *pkey;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 	/*
 	 * The content field in the PKCS7 ContentInfo is optional, but that really
 	 * only applies to inner content (precisely, detached signatures).
 	 *
 	 * When reading content, missing outer content is therefore treated as an
 	 * error.
 	 *
 	 * When creating content, PKCS7_content_new() must be called before
 	 * calling this method, so a NULL p7->d is always an error.
 	 */
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		md_sk=p7->d.sign->md_algs;
 		os = PKCS7_get_octet_string(p7->d.sign->contents);
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		xalg=p7->d.enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_digest:
 		xa = p7->d.digest->md;
 		os = PKCS7_get_octet_string(p7->d.digest->contents);
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
 	for (i=0; ialgorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
 		if (ivlen > 0)
 			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
 				goto err;
 		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
 			goto err;
 		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
 			goto err;
 
 		if (ivlen > 0) {
 			if (xalg->parameter == NULL) {
 				xalg->parameter = ASN1_TYPE_new();
 				if (xalg->parameter == NULL)
 					goto err;
 			}
 			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
 			       goto err;
 		}
 
 		/* Lets do the pub key stuff :-) */
 		max=0;
 		for (i=0; icert == NULL)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
 				goto err;
 				}
 			if ((pkey=X509_get_pubkey(ri->cert)) == NULL)
 				goto err;
 			jj=EVP_PKEY_size(pkey);
 			EVP_PKEY_free(pkey);
 			if (max < jj) max=jj;
 			}
 		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		for (i=0; icert)) == NULL)
 				goto err;
 			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
 			EVP_PKEY_free(pkey);
 			if (jj <= 0)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
 				OPENSSL_free(tmp);
 				goto err;
 				}
 			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 					ERR_R_MALLOC_FAILURE);
 				OPENSSL_free(tmp);
 				goto err;
 				}
 			}
 		OPENSSL_free(tmp);
 		OPENSSL_cleanse(key, keylen);
 
 		if (out == NULL)
 			out=btmp;
 		else
 			BIO_push(out,btmp);
 		btmp=NULL;
 		}
 
 	if (bio == NULL)
 		{
 		if (PKCS7_is_detached(p7))
 			bio=BIO_new(BIO_s_null());
 		else if (os && os->length > 0)
 			bio = BIO_new_mem_buf(os->data, os->length);
 		if(bio == NULL)
 			{
 			bio=BIO_new(BIO_s_mem());
 			if (bio == NULL)
 				goto err;
 			BIO_set_mem_eof_return(bio,0);
 			}
 		}
 	BIO_push(out,bio);
 	bio=NULL;
 	if (0)
 		{
 err:
 		if (out != NULL)
 			BIO_free_all(out);
 		if (btmp != NULL)
 			BIO_free_all(btmp);
 		out=NULL;
 		}
 	return(out);
 	}
 
 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
 	{
 	int ret;
 	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
 				pcert->cert_info->issuer);
 	if (ret)
 		return ret;
 	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
 					ri->issuer_and_serial->serial);
 	}
 
 /* int */
 BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 	{
 	int i,j;
 	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
 	unsigned char *tmp=NULL;
 	X509_ALGOR *xa;
 	ASN1_OCTET_STRING *data_body=NULL;
 	const EVP_MD *evp_md;
 	const EVP_CIPHER *evp_cipher=NULL;
 	EVP_CIPHER_CTX *evp_ctx=NULL;
 	X509_ALGOR *enc_alg=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
 		md_sk=p7->d.sign->md_algs;
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
 		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		enc_alg=p7->d.enveloped->enc_data->algorithm;
 		data_body=p7->d.enveloped->enc_data->enc_data;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
+    /* Detached content must be supplied via in_bio instead. */
+    if (data_body == NULL && in_bio == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+        goto err;
+    }
+
 	/* We will be checking the signature */
 	if (md_sk != NULL)
 		{
 		for (i=0; ialgorithm);
 			evp_md=EVP_get_digestbynid(j);
 			if (evp_md == NULL)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 				goto err;
 				}
 
 			BIO_set_md(btmp,evp_md);
 			if (out == NULL)
 				out=btmp;
 			else
 				BIO_push(out,btmp);
 			btmp=NULL;
 			}
 		}
 
 	if (evp_cipher != NULL)
 		{
 #if 0
 		unsigned char key[EVP_MAX_KEY_LENGTH];
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char *p;
 		int keylen,ivlen;
 		int max;
 		X509_OBJECT ret;
 #endif
 		unsigned char *tkey = NULL;
 		int tkeylen;
 		int jj;
 
 		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
 			goto err;
 			}
 
 		/* It was encrypted, we need to decrypt the secret key
 		 * with the private key */
 
 		/* Find the recipientInfo which matches the passed certificate
 		 * (if any)
 		 */
 
 		if (pcert) {
 			for (i=0; ienc_key),
 					M_ASN1_STRING_length(ri->enc_key),
 						pkey);
 				if (tret > 0)
 					{
 					memcpy(tmp, tmp2, tret);
 					OPENSSL_cleanse(tmp2, tret);
 					jj = tret;
 					}
 				ERR_clear_error();
 				}
 			OPENSSL_free(tmp2);
 			}
 		else
 			{
 			jj=EVP_PKEY_decrypt(tmp,
 				M_ASN1_STRING_data(ri->enc_key),
 				M_ASN1_STRING_length(ri->enc_key), pkey);
 			ERR_clear_error();
 			}
 
 		evp_ctx=NULL;
 		BIO_get_cipher_ctx(etmp,&evp_ctx);
 		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
 			goto err;
 		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
 			goto err;
 		/* Generate random key to counter MMA */
 		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
 		tkey = OPENSSL_malloc(tkeylen);
 		if (!tkey)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
 			goto err;
 		/* If we have no key use random key */
 		if (jj <= 0)
 			{
 			OPENSSL_free(tmp);
 			jj = tkeylen;
 			tmp = tkey;
 			tkey = NULL;
 			}
 
 		if (jj != tkeylen) {
 			/* Some S/MIME clients don't use the same key
 			 * and effective key length. The key length is
 			 * determined by the size of the decrypted RSA key.
 			 */
 			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
 				{
 				/* As MMA defence use random key instead */
 				OPENSSL_cleanse(tmp, jj);
 				OPENSSL_free(tmp);
 				jj = tkeylen;
 				tmp = tkey;
 				tkey = NULL;
 				}
 		} 
 		ERR_clear_error();
 		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
 			goto err;
 
 		OPENSSL_cleanse(tmp,jj);
 
 		if (tkey)
 			{
 			OPENSSL_cleanse(tkey, tkeylen);
 			OPENSSL_free(tkey);
 			}
 
 		if (out == NULL)
 			out=etmp;
 		else
 			BIO_push(out,etmp);
 		etmp=NULL;
 		}
 
 #if 1
-	if (PKCS7_is_detached(p7) || (in_bio != NULL))
-		{
-		bio=in_bio;
-		}
-	else 
-		{
+	if (in_bio != NULL) {
+		bio = in_bio;
+	} else {
 #if 0
 		bio=BIO_new(BIO_s_mem());
 		/* We need to set this so that when we have read all
 		 * the data, the encrypt BIO, if present, will read
 		 * EOF and encode the last few bytes */
 		BIO_set_mem_eof_return(bio,0);
 
 		if (data_body->length > 0)
 			BIO_write(bio,(char *)data_body->data,data_body->length);
 #else
 		if (data_body->length > 0)
 		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
 		else {
 			bio=BIO_new(BIO_s_mem());
 			BIO_set_mem_eof_return(bio,0);
 		}
 		if (bio == NULL)
 			goto err;
 #endif
 		}
 	BIO_push(out,bio);
 	bio=NULL;
 #endif
 	if (0)
 		{
 err:
 		if (out != NULL) BIO_free_all(out);
 		if (btmp != NULL) BIO_free_all(btmp);
 		if (etmp != NULL) BIO_free_all(etmp);
 		if (bio != NULL) BIO_free_all(bio);
 		out=NULL;
 		}
 	if (tmp != NULL)
 		OPENSSL_free(tmp);
 	return(out);
 	}
 
 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
 	{
 	for (;;)
 		{
 		bio=BIO_find_type(bio,BIO_TYPE_MD);
 		if (bio == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			return NULL;	
 			}
 		BIO_get_md_ctx(bio,pmd);
 		if (*pmd == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}	
 		if (EVP_MD_CTX_type(*pmd) == nid)
 			return bio;
 		bio=BIO_next(bio);
 		}
 	return NULL;
 	}
 
 int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 	{
 	int ret=0;
 	int i,j;
 	BIO *btmp;
 	BUF_MEM *buf_mem=NULL;
 	BUF_MEM *buf=NULL;
 	PKCS7_SIGNER_INFO *si;
 	EVP_MD_CTX *mdc,ctx_tmp;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	EVP_MD_CTX_init(&ctx_tmp);
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signedAndEnveloped:
 		/* XXXXXXXXXXXXXXXX */
 		si_sk=p7->d.signed_and_enveloped->signer_info;
 		if (!(os=M_ASN1_OCTET_STRING_new()))
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		p7->d.signed_and_enveloped->enc_data->enc_data=os;
 		break;
 	case NID_pkcs7_enveloped:
 		/* XXXXXXXXXXXXXXXX */
 		if (!(os=M_ASN1_OCTET_STRING_new()))
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		p7->d.enveloped->enc_data->enc_data=os;
 		break;
 	case NID_pkcs7_signed:
 		si_sk=p7->d.sign->signer_info;
 		os=PKCS7_get_octet_string(p7->d.sign->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.sign->contents->d.data = NULL;
 		}
 		break;
 
 	case NID_pkcs7_digest:
 		os=PKCS7_get_octet_string(p7->d.digest->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
 			{
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.digest->contents->d.data = NULL;
 			}
 		break;
 
 		}
 
 	if (si_sk != NULL)
 		{
 		if ((buf=BUF_MEM_new()) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
 			goto err;
 			}
 		for (i=0; ipkey == NULL) continue;
 
 			j=OBJ_obj2nid(si->digest_alg->algorithm);
 
 			btmp=bio;
 
 			btmp = PKCS7_find_digest(&mdc, btmp, j);
 
 			if (btmp == NULL)
 				goto err;
 
 			/* We now have the EVP_MD_CTX, lets do the
 			 * signing. */
 			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
 			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
 				goto err;
 				}
 
 			sk=si->auth_attr;
 
 			/* If there are attributes, we add the digest
 			 * attribute and only sign the attributes */
 			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
 				{
 				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
 				unsigned int md_len, alen;
 				ASN1_OCTET_STRING *digest;
 				ASN1_UTCTIME *sign_time;
 				const EVP_MD *md_tmp;
 
 				/* Add signing time if not already present */
 				if (!PKCS7_get_signed_attribute(si,
 							NID_pkcs9_signingTime))
 					{
 					if (!(sign_time=X509_gmtime_adj(NULL,0)))
 						{
 						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 							ERR_R_MALLOC_FAILURE);
 						goto err;
 						}
 					if (!PKCS7_add_signed_attribute(si,
 						NID_pkcs9_signingTime,
 						V_ASN1_UTCTIME,sign_time))
 						{
 						M_ASN1_UTCTIME_free(sign_time);
 						goto err;
 						}
 					}
 
 				/* Add digest */
 				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
 				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
 				if (!(digest=M_ASN1_OCTET_STRING_new()))
 					{
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 						ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
 								md_len))
 					{
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 						ERR_R_MALLOC_FAILURE);
 					M_ASN1_OCTET_STRING_free(digest);
 					goto err;
 					}
 				if (!PKCS7_add_signed_attribute(si,
 					NID_pkcs9_messageDigest,
 					V_ASN1_OCTET_STRING,digest))
 					{
 					M_ASN1_OCTET_STRING_free(digest);
 					goto err;
 					}
 
 				/* Now sign the attributes */
 				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
 				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
 							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
 				if(!abuf) goto err;
 				EVP_SignUpdate(&ctx_tmp,abuf,alen);
 				OPENSSL_free(abuf);
 				}
 
 #ifndef OPENSSL_NO_DSA
 			if (si->pkey->type == EVP_PKEY_DSA)
 				ctx_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
  			if (si->pkey->type == EVP_PKEY_EC)
  				ctx_tmp.digest=EVP_ecdsa();
 #endif
 
 			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
 				(unsigned int *)&buf->length,si->pkey))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
 				goto err;
 				}
 			if (!ASN1_STRING_set(si->enc_digest,
 				(unsigned char *)buf->data,buf->length))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
 				goto err;
 				}
 			}
 		}
 	else if (i == NID_pkcs7_digest)
 		{
 		unsigned char md_data[EVP_MAX_MD_SIZE];
 		unsigned int md_len;
 		if (!PKCS7_find_digest(&mdc, bio,
 				OBJ_obj2nid(p7->d.digest->md->algorithm)))
 			goto err;
 		EVP_DigestFinal_ex(mdc,md_data,&md_len);
 		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
 		}
 
 	if (!PKCS7_is_detached(p7)) {
 		/*
 		 * NOTE(emilia): I think we only reach os == NULL here because detached
 		 * digested data support is broken.
 		 */
 		if (os == NULL)
 			goto err;
 		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
 		if (btmp == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
 			goto err;
 			}
 		BIO_get_mem_ptr(btmp,&buf_mem);
 		/* Mark the BIO read only then we can use its copy of the data
 		 * instead of making an extra copy.
 		 */
 		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
 		BIO_set_mem_eof_return(btmp, 0);
 		os->data = (unsigned char *)buf_mem->data;
 		os->length = buf_mem->length;
 #if 0
 		M_ASN1_OCTET_STRING_set(os,
 			(unsigned char *)buf_mem->data,buf_mem->length);
 #endif
 		}
 	ret=1;
 err:
 	EVP_MD_CTX_cleanup(&ctx_tmp);
 	if (buf != NULL) BUF_MEM_free(buf);
 	return(ret);
 	}
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
 	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 	{
 	PKCS7_ISSUER_AND_SERIAL *ias;
 	int ret=0,i;
 	STACK_OF(X509) *cert;
 	X509 *x509;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	if (PKCS7_type_is_signed(p7))
 		{
 		cert=p7->d.sign->cert;
 		}
 	else if (PKCS7_type_is_signedAndEnveloped(p7))
 		{
 		cert=p7->d.signed_and_enveloped->cert;
 		}
 	else
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 		}
 	/* XXXXXXXXXXXXXXXXXXXXXXX */
 	ias=si->issuer_and_serial;
 
 	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
 
 	/* were we able to find the cert in passed to us */
 	if (x509 == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
 		goto err;
 		}
 
 	/* Lets verify */
 	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		goto err;
 		}
 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
 	i=X509_verify_cert(ctx);
 	if (i <= 0) 
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		X509_STORE_CTX_cleanup(ctx);
 		goto err;
 		}
 	X509_STORE_CTX_cleanup(ctx);
 
 	return PKCS7_signatureVerify(bio, p7, si, x509);
 	err:
 	return ret;
 	}
 
 int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
 								X509 *x509)
 	{
 	ASN1_OCTET_STRING *os;
 	EVP_MD_CTX mdc_tmp,*mdc;
 	int ret=0,i;
 	int md_type;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	BIO *btmp;
 	EVP_PKEY *pkey;
 
 	EVP_MD_CTX_init(&mdc_tmp);
 
 	if (!PKCS7_type_is_signed(p7) && 
 				!PKCS7_type_is_signedAndEnveloped(p7)) {
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 	}
 
 	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
 
 	btmp=bio;
 	for (;;)
 		{
 		if ((btmp == NULL) ||
 			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		BIO_get_md_ctx(btmp,&mdc);
 		if (mdc == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 							ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		if (EVP_MD_CTX_type(mdc) == md_type)
 			break;
 		/* Workaround for some broken clients that put the signature
 		 * OID instead of the digest OID in digest_alg->algorithm
 		 */
 		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
 			break;
 		btmp=BIO_next(btmp);
 		}
 
 	/* mdc is the digest ctx that we want, unless there are attributes,
 	 * in which case the digest is the signed attributes */
 	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
 
 	sk=si->auth_attr;
 	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
 		{
 		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
                 unsigned int md_len, alen;
 		ASN1_OCTET_STRING *message_digest;
 
 		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
 		message_digest=PKCS7_digest_from_attributes(sk);
 		if (!message_digest)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		if ((message_digest->length != (int)md_len) ||
 			(memcmp(message_digest->data,md_dat,md_len)))
 			{
 #if 0
 {
 int ii;
 for (ii=0; iilength; ii++)
 	printf("%02X",message_digest->data[ii]); printf(" sent\n");
 for (ii=0; iienc_digest;
 	pkey = X509_get_pubkey(x509);
 	if (!pkey)
 		{
 		ret = -1;
 		goto err;
 		}
 #ifndef OPENSSL_NO_DSA
 	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
 #endif
 
 	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
 	EVP_PKEY_free(pkey);
 	if (i <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_SIGNATURE_FAILURE);
 		ret= -1;
 		goto err;
 		}
 	else
 		ret=1;
 err:
 	EVP_MD_CTX_cleanup(&mdc_tmp);
 	return(ret);
 	}
 
 PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
 	{
 	STACK_OF(PKCS7_RECIP_INFO) *rsk;
 	PKCS7_RECIP_INFO *ri;
 	int i;
 
 	i=OBJ_obj2nid(p7->type);
 	if (i != NID_pkcs7_signedAndEnveloped)
 		return NULL;
 	if (p7->d.signed_and_enveloped == NULL)
 		return NULL;
 	rsk=p7->d.signed_and_enveloped->recipientinfo;
 	if (rsk == NULL)
 		return NULL;
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
 	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
 	return(ri->issuer_and_serial);
 	}
 
 ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->auth_attr,nid));
 	}
 
 ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->unauth_attr,nid));
 	}
 
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
 	{
 	int i;
 	X509_ATTRIBUTE *xa;
 	ASN1_OBJECT *o;
 
 	o=OBJ_nid2obj(nid);
 	if (!o || !sk) return(NULL);
 	for (i=0; iobject,o) == 0)
 			{
 			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
 				return(sk_ASN1_TYPE_value(xa->value.set,0));
 			else
 				return(NULL);
 			}
 		}
 	return(NULL);
 	}
 
 ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
 {
 	ASN1_TYPE *astype;
 	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
 	return astype->value.octet_string;
 }
 
 int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
 				STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->auth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
 	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->auth_attr == NULL)
 		return 0;
 	for (i=0; iauth_attr,i,
 			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->unauth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
 					   X509_ATTRIBUTE_free);
 	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->unauth_attr == NULL)
 		return 0;
 	for (i=0; iunauth_attr,i,
                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
 	}
 
 int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
 	}
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value)
 	{
 	X509_ATTRIBUTE *attr=NULL;
 
 	if (*sk == NULL)
 		{
 		if (!(*sk = sk_X509_ATTRIBUTE_new_null()))
 			return 0;
 new_attrib:
 		if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value)))
 			return 0;
 		if (!sk_X509_ATTRIBUTE_push(*sk,attr))
 			{
 			X509_ATTRIBUTE_free(attr);
 			return 0;
 			}
 		}
 	else
 		{
 		int i;
 
 		for (i=0; iobject) == nid)
 				{
 				X509_ATTRIBUTE_free(attr);
 				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
 				if (attr == NULL)
 					return 0;
 				if (!sk_X509_ATTRIBUTE_set(*sk,i,attr))
 					{
 					X509_ATTRIBUTE_free(attr);
 					return 0;
 					}
 				goto end;
 				}
 			}
 		goto new_attrib;
 		}
 end:
 	return(1);
 	}
 
Index: releng/8.4/crypto/openssl/crypto/x509/x509_vfy.c
===================================================================
--- releng/8.4/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284294)
+++ releng/8.4/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284295)
@@ -1,1545 +1,1583 @@
 /* crypto/x509/x509_vfy.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
 static int null_callback(int ok,X509_STORE_CTX *e);
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
 static int check_chain_extensions(X509_STORE_CTX *ctx);
 static int check_trust(X509_STORE_CTX *ctx);
 static int check_revocation(X509_STORE_CTX *ctx);
 static int check_cert(X509_STORE_CTX *ctx);
 static int check_policy(X509_STORE_CTX *ctx);
 static int internal_verify(X509_STORE_CTX *ctx);
 const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT;
 
 
 static int null_callback(int ok, X509_STORE_CTX *e)
 	{
 	return ok;
 	}
 
 #if 0
 static int x509_subject_cmp(X509 **a, X509 **b)
 	{
 	return X509_subject_name_cmp(*a,*b);
 	}
 #endif
 
 int X509_verify_cert(X509_STORE_CTX *ctx)
 	{
 	X509 *x,*xtmp,*chain_ss=NULL;
 	int bad_chain = 0;
 	X509_VERIFY_PARAM *param = ctx->param;
 	int depth,i,ok=0;
 	int num;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	STACK_OF(X509) *sktmp=NULL;
 	if (ctx->cert == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
 		return -1;
 		}
 
 	cb=ctx->verify_cb;
 
 	/* first we make sure the chain we are going to build is
 	 * present and that the first entry is in place */
 	if (ctx->chain == NULL)
 		{
 		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
 			(!sk_X509_push(ctx->chain,ctx->cert)))
 			{
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			goto end;
 			}
 		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
 		ctx->last_untrusted=1;
 		}
 
 	/* We use a temporary STACK so we can chop and hack at it */
 	if (ctx->untrusted != NULL
 	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 		goto end;
 		}
 
 	num=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,num-1);
 	depth=param->depth;
 
 
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break; /* FIXME: If this happens, we should take
 		                         * note of it and, if appropriate, use the
 		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
 		                         * code later.
 		                         */
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx, x,x)) break;
 
 		/* If we were passed a cert chain, use it first */
 		if (ctx->untrusted != NULL)
 			{
 			xtmp=find_issuer(ctx, sktmp,x);
 			if (xtmp != NULL)
 				{
 				if (!sk_X509_push(ctx->chain,xtmp))
 					{
 					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 					goto end;
 					}
 				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
 				(void)sk_X509_delete_ptr(sktmp,xtmp);
 				ctx->last_untrusted++;
 				x=xtmp;
 				num++;
 				/* reparse the full chain for
 				 * the next one */
 				continue;
 				}
 			}
 		break;
 		}
 
 	/* at this point, chain should contain a list of untrusted
 	 * certificates.  We now need to add at least one trusted one,
 	 * if possible, otherwise we complain. */
 
 	/* Examine last certificate in chain and see if it
  	 * is self signed.
  	 */
 
 	i=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,i-1);
 	if (ctx->check_issued(ctx, x, x))
 		{
 		/* we have a self signed certificate */
 		if (sk_X509_num(ctx->chain) == 1)
 			{
 			/* We have a single self signed certificate: see if
 			 * we can find it in the store. We must have an exact
 			 * match to avoid possible impersonation.
 			 */
 			ok = ctx->get_issuer(&xtmp, ctx, x);
 			if ((ok <= 0) || X509_cmp(x, xtmp)) 
 				{
 				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
 				ctx->current_cert=x;
 				ctx->error_depth=i-1;
 				if (ok == 1) X509_free(xtmp);
 				bad_chain = 1;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			else 
 				{
 				/* We have a match: replace certificate with store version
 				 * so we get any trust settings.
 				 */
 				X509_free(x);
 				x = xtmp;
 				(void)sk_X509_set(ctx->chain, i - 1, x);
 				ctx->last_untrusted=0;
 				}
 			}
 		else
 			{
 			/* extract and save self signed certificate for later use */
 			chain_ss=sk_X509_pop(ctx->chain);
 			ctx->last_untrusted--;
 			num--;
 			x=sk_X509_value(ctx->chain,num-1);
 			}
 		}
 
 	/* We now lookup certs from the certificate store */
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break;
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx,x,x)) break;
 
 		ok = ctx->get_issuer(&xtmp, ctx, x);
 
 		if (ok < 0) return ok;
 		if (ok == 0) break;
 
 		x = xtmp;
 		if (!sk_X509_push(ctx->chain,x))
 			{
 			X509_free(xtmp);
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		num++;
 		}
 
 	/* we now have our chain, lets check it... */
 
 	/* Is last certificate looked up self signed? */
 	if (!ctx->check_issued(ctx,x,x))
 		{
 		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
 			{
 			if (ctx->last_untrusted >= num)
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
 			else
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
 			ctx->current_cert=x;
 			}
 		else
 			{
 
 			sk_X509_push(ctx->chain,chain_ss);
 			num++;
 			ctx->last_untrusted=num;
 			ctx->current_cert=chain_ss;
 			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
 			chain_ss=NULL;
 			}
 
 		ctx->error_depth=num-1;
 		bad_chain = 1;
 		ok=cb(0,ctx);
 		if (!ok) goto end;
 		}
 
 	/* We have the chain complete: now we need to check its purpose */
 	ok = check_chain_extensions(ctx);
 
 	if (!ok) goto end;
 
 	/* The chain extensions are OK: check trust */
 
 	if (param->trust > 0) ok = check_trust(ctx);
 
 	if (!ok) goto end;
 
 	/* We may as well copy down any DSA parameters that are required */
 	X509_get_pubkey_parameters(NULL,ctx->chain);
 
 	/* Check revocation status: we do this after copying parameters
 	 * because they may be needed for CRL signature verification.
 	 */
 
 	ok = ctx->check_revocation(ctx);
 	if(!ok) goto end;
 
 	/* At this point, we have a chain and need to verify it */
 	if (ctx->verify != NULL)
 		ok=ctx->verify(ctx);
 	else
 		ok=internal_verify(ctx);
 	if(!ok) goto end;
 
 #ifndef OPENSSL_NO_RFC3779
 	/* RFC 3779 path validation, now that CRL check has been done */
 	ok = v3_asid_validate_path(ctx);
 	if (!ok) goto end;
 	ok = v3_addr_validate_path(ctx);
 	if (!ok) goto end;
 #endif
 
 	/* If we get this far evaluate policies */
 	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
 		ok = ctx->check_policy(ctx);
 	if(!ok) goto end;
 	if (0)
 		{
 end:
 		X509_get_pubkey_parameters(NULL,ctx->chain);
 		}
 	if (sktmp != NULL) sk_X509_free(sktmp);
 	if (chain_ss != NULL) X509_free(chain_ss);
 	return ok;
 	}
 
 
 /* Given a STACK_OF(X509) find the issuer of cert (if any)
  */
 
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
 {
 	int i;
 	X509 *issuer;
 	for (i = 0; i < sk_X509_num(sk); i++)
 		{
 		issuer = sk_X509_value(sk, i);
 		if (ctx->check_issued(ctx, x, issuer))
 			return issuer;
 		}
 	return NULL;
 }
 
 /* Given a possible certificate and issuer check them */
 
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
 {
 	int ret;
 	ret = X509_check_issued(issuer, x);
 	if (ret == X509_V_OK)
 		return 1;
 	/* If we haven't asked for issuer errors don't set ctx */
 	if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
 		return 0;
 
 	ctx->error = ret;
 	ctx->current_cert = x;
 	ctx->current_issuer = issuer;
 	return ctx->verify_cb(0, ctx);
 	return 0;
 }
 
 /* Alternative lookup method: look from a STACK stored in other_ctx */
 
 static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 {
 	*issuer = find_issuer(ctx, ctx->other_ctx, x);
 	if (*issuer)
 		{
 		CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
 		return 1;
 		}
 	else
 		return 0;
 }
 	
 
 /* Check a certificate chains extensions for consistency
  * with the supplied purpose
  */
 
 static int check_chain_extensions(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok=0, must_be_ca, plen = 0;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	int proxy_path_length = 0;
 	int allow_proxy_certs =
 		!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
 	cb=ctx->verify_cb;
 
 	/* must_be_ca can have 1 of 3 values:
 	   -1: we accept both CA and non-CA certificates, to allow direct
 	       use of self-signed certificates (which are marked as CA).
 	   0:  we only accept non-CA certificates.  This is currently not
 	       used, but the possibility is present for future extensions.
 	   1:  we only accept CA certificates.  This is currently used for
 	       all certificates in the chain except the leaf certificate.
 	*/
 	must_be_ca = -1;
 
 	/* A hack to keep people who don't want to modify their software
 	   happy */
 	if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
 		allow_proxy_certs = 1;
 
 	/* Check all untrusted certificates */
 	for (i = 0; i < ctx->last_untrusted; i++)
 		{
 		int ret;
 		x = sk_X509_value(ctx->chain, i);
 		if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 			&& (x->ex_flags & EXFLAG_CRITICAL))
 			{
 			ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
 			{
 			ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		ret = X509_check_ca(x);
 		switch(must_be_ca)
 			{
 		case -1:
 			if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 				&& (ret != 1) && (ret != 0))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 		case 0:
 			if (ret != 0)
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_NON_CA;
 				}
 			else
 				ret = 1;
 			break;
 		default:
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 			}
 		if (ret == 0)
 			{
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (ctx->param->purpose > 0)
 			{
 			ret = X509_check_purpose(x, ctx->param->purpose,
 				must_be_ca > 0);
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ctx->error = X509_V_ERR_INVALID_PURPOSE;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			}
 		/* Check pathlen if not self issued */
 		if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
 			   && (x->ex_pathlen != -1)
 			   && (plen > (x->ex_pathlen + proxy_path_length + 1)))
 			{
 			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		/* Increment path length if not self issued */
 		if (!(x->ex_flags & EXFLAG_SI))
 			plen++;
 		/* If this certificate is a proxy certificate, the next
 		   certificate must be another proxy certificate or a EE
 		   certificate.  If not, the next certificate must be a
 		   CA certificate.  */
 		if (x->ex_flags & EXFLAG_PROXY)
 			{
 			if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
 				{
 				ctx->error =
 					X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			proxy_path_length++;
 			must_be_ca = 0;
 			}
 		else
 			must_be_ca = 1;
 		}
 	ok = 1;
  end:
 	return ok;
 #endif
 }
 
 static int check_trust(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	cb=ctx->verify_cb;
 /* For now just check the last certificate in the chain */
 	i = sk_X509_num(ctx->chain) - 1;
 	x = sk_X509_value(ctx->chain, i);
 	ok = X509_check_trust(x, ctx->param->trust, 0);
 	if (ok == X509_TRUST_TRUSTED)
 		return 1;
 	ctx->error_depth = i;
 	ctx->current_cert = x;
 	if (ok == X509_TRUST_REJECTED)
 		ctx->error = X509_V_ERR_CERT_REJECTED;
 	else
 		ctx->error = X509_V_ERR_CERT_UNTRUSTED;
 	ok = cb(0, ctx);
 	return ok;
 #endif
 }
 
 static int check_revocation(X509_STORE_CTX *ctx)
 	{
 	int i, last, ok;
 	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
 		return 1;
 	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
 		last = sk_X509_num(ctx->chain) - 1;
 	else
 		last = 0;
 	for(i = 0; i <= last; i++)
 		{
 		ctx->error_depth = i;
 		ok = check_cert(ctx);
 		if (!ok) return ok;
 		}
 	return 1;
 	}
 
 static int check_cert(X509_STORE_CTX *ctx)
 	{
 	X509_CRL *crl = NULL;
 	X509 *x;
 	int ok, cnum;
 	cnum = ctx->error_depth;
 	x = sk_X509_value(ctx->chain, cnum);
 	ctx->current_cert = x;
 	/* Try to retrieve relevant CRL */
 	ok = ctx->get_crl(ctx, &crl, x);
 	/* If error looking up CRL, nothing we can do except
 	 * notify callback
 	 */
 	if(!ok)
 		{
 		ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
 		ok = ctx->verify_cb(0, ctx);
 		goto err;
 		}
 	ctx->current_crl = crl;
 	ok = ctx->check_crl(ctx, crl);
 	if (!ok) goto err;
 	ok = ctx->cert_crl(ctx, crl, x);
 	err:
 	ctx->current_crl = NULL;
 	X509_CRL_free(crl);
 	return ok;
 
 	}
 
 /* Check CRL times against values in X509_STORE_CTX */
 
 static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
 	{
 	time_t *ptime;
 	int i;
 	ctx->current_crl = crl;
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
 		if (!notify || !ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
 		if (!notify || !ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if(X509_CRL_get_nextUpdate(crl))
 		{
 		i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
 
 		if (i == 0)
 			{
 			ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
 			if (!notify || !ctx->verify_cb(0, ctx))
 				return 0;
 			}
 
 		if (i < 0)
 			{
 			ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
 			if (!notify || !ctx->verify_cb(0, ctx))
 				return 0;
 			}
 		}
 
 	ctx->current_crl = NULL;
 
 	return 1;
 	}
 
 /* Lookup CRLs from the supplied list. Look for matching isser name
  * and validity. If we can't find a valid CRL return the last one
  * with matching name. This gives more meaningful error codes. Otherwise
  * we'd get a CRL not found error if a CRL existed with matching name but
  * was invalid.
  */
 
 static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl,
 			X509_NAME *nm, STACK_OF(X509_CRL) *crls)
 	{
 	int i;
 	X509_CRL *crl, *best_crl = NULL;
 	for (i = 0; i < sk_X509_CRL_num(crls); i++)
 		{
 		crl = sk_X509_CRL_value(crls, i);
 		if (X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
 			continue;
 		if (check_crl_time(ctx, crl, 0))
 			{
 			*pcrl = crl;
 			CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509);
 			return 1;
 			}
 		best_crl = crl;
 		}
 	if (best_crl)
 		{
 		*pcrl = best_crl;
 		CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509);
 		}
 		
 	return 0;
 	}
 
 /* Retrieve CRL corresponding to certificate: currently just a
  * subject lookup: maybe use AKID later...
  */
 static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x)
 	{
 	int ok;
 	X509_CRL *crl = NULL;
 	X509_OBJECT xobj;
 	X509_NAME *nm;
 	nm = X509_get_issuer_name(x);
 	ok = get_crl_sk(ctx, &crl, nm, ctx->crls);
 	if (ok)
 		{
 		*pcrl = crl;
 		return 1;
 		}
 
 	ok = X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj);
 
 	if (!ok)
 		{
 		/* If we got a near match from get_crl_sk use that */
 		if (crl)
 			{
 			*pcrl = crl;
 			return 1;
 			}
 		return 0;
 		}
 
 	*pcrl = xobj.data.crl;
 	if (crl)
 		X509_CRL_free(crl);
 	return 1;
 	}
 
 /* Check CRL validity */
 static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
 	{
 	X509 *issuer = NULL;
 	EVP_PKEY *ikey = NULL;
 	int ok = 0, chnum, cnum;
 	cnum = ctx->error_depth;
 	chnum = sk_X509_num(ctx->chain) - 1;
 	/* Find CRL issuer: if not last certificate then issuer
 	 * is next certificate in chain.
 	 */
 	if(cnum < chnum)
 		issuer = sk_X509_value(ctx->chain, cnum + 1);
 	else
 		{
 		issuer = sk_X509_value(ctx->chain, chnum);
 		/* If not self signed, can't check signature */
 		if(!ctx->check_issued(ctx, issuer, issuer))
 			{
 			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) goto err;
 			}
 		}
 
 	if(issuer)
 		{
 		/* Check for cRLSign bit if keyUsage present */
 		if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
 			!(issuer->ex_kusage & KU_CRL_SIGN))
 			{
 			ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) goto err;
 			}
 
 		/* Attempt to get issuer certificate public key */
 		ikey = X509_get_pubkey(issuer);
 
 		if(!ikey)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 			ok = ctx->verify_cb(0, ctx);
 			if (!ok) goto err;
 			}
 		else
 			{
 			/* Verify CRL signature */
 			if(X509_CRL_verify(crl, ikey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
 				ok = ctx->verify_cb(0, ctx);
 				if (!ok) goto err;
 				}
 			}
 		}
 
 	ok = check_crl_time(ctx, crl, 1);
 	if (!ok)
 		goto err;
 
 	ok = 1;
 
 	err:
 	EVP_PKEY_free(ikey);
 	return ok;
 	}
 
 /* Check certificate against CRL */
 static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 	{
 	int idx, ok;
 	X509_REVOKED rtmp;
 	STACK_OF(X509_EXTENSION) *exts;
 	X509_EXTENSION *ext;
 	/* Look for serial number of certificate in CRL */
 	rtmp.serialNumber = X509_get_serialNumber(x);
 	/* Sort revoked into serial number order if not already sorted.
 	 * Do this under a lock to avoid race condition.
  	 */
 	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
 		{
 		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
 		sk_X509_REVOKED_sort(crl->crl->revoked);
 		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
 		}
 	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
 	/* If found assume revoked: want something cleverer than
 	 * this to handle entry extensions in V2 CRLs.
 	 */
 	if(idx >= 0)
 		{
 		ctx->error = X509_V_ERR_CERT_REVOKED;
 		ok = ctx->verify_cb(0, ctx);
 		if (!ok) return 0;
 		}
 
 	if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 		return 1;
 
 	/* See if we have any critical CRL extensions: since we
 	 * currently don't handle any CRL extensions the CRL must be
 	 * rejected. 
 	 * This code accesses the X509_CRL structure directly: applications
 	 * shouldn't do this.
 	 */
 
 	exts = crl->crl->extensions;
 
 	for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
 		{
 		ext = sk_X509_EXTENSION_value(exts, idx);
 		if (ext->critical > 0)
 			{
 			ctx->error =
 				X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) return 0;
 			break;
 			}
 		}
 	return 1;
 	}
 
 static int check_policy(X509_STORE_CTX *ctx)
 	{
 	int ret;
 	ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
 				ctx->param->policies, ctx->param->flags);
 	if (ret == 0)
 		{
 		X509err(X509_F_CHECK_POLICY,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	/* Invalid or inconsistent extensions */
 	if (ret == -1)
 		{
 		/* Locate certificates with bad extensions and notify
 		 * callback.
 		 */
 		X509 *x;
 		int i;
 		for (i = 1; i < sk_X509_num(ctx->chain); i++)
 			{
 			x = sk_X509_value(ctx->chain, i);
 			if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
 				continue;
 			ctx->current_cert = x;
 			ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
 			ret = ctx->verify_cb(0, ctx);
 			}
 		return 1;
 		}
 	if (ret == -2)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
 		return ctx->verify_cb(0, ctx);
 		}
 
 	if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_OK;
 		if (!ctx->verify_cb(2, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
 	{
 	time_t *ptime;
 	int i;
 
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_get_notBefore(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	i=X509_cmp_time(X509_get_notAfter(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i < 0)
 		{
 		ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int internal_verify(X509_STORE_CTX *ctx)
 	{
 	int ok=0,n;
 	X509 *xs,*xi;
 	EVP_PKEY *pkey=NULL;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 
 	cb=ctx->verify_cb;
 
 	n=sk_X509_num(ctx->chain);
 	ctx->error_depth=n-1;
 	n--;
 	xi=sk_X509_value(ctx->chain,n);
 
 	if (ctx->check_issued(ctx, xi, xi))
 		xs=xi;
 	else
 		{
 		if (n <= 0)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
 			ctx->current_cert=xi;
 			ok=cb(0,ctx);
 			goto end;
 			}
 		else
 			{
 			n--;
 			ctx->error_depth=n;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 
 /*	ctx->error=0;  not needed */
 	while (n >= 0)
 		{
 		ctx->error_depth=n;
 
 		/* Skip signature check for self signed certificates unless
 		 * explicitly asked for. It doesn't add any security and
 		 * just wastes time.
 		 */
 		if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
 			{
 			if ((pkey=X509_get_pubkey(xi)) == NULL)
 				{
 				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 				ctx->current_cert=xi;
 				ok=(*cb)(0,ctx);
 				if (!ok) goto end;
 				}
 			else if (X509_verify(xs,pkey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
 				ctx->current_cert=xs;
 				ok=(*cb)(0,ctx);
 				if (!ok)
 					{
 					EVP_PKEY_free(pkey);
 					goto end;
 					}
 				}
 			EVP_PKEY_free(pkey);
 			pkey=NULL;
 			}
 
 		xs->valid = 1;
 
 		ok = check_cert_time(ctx, xs);
 		if (!ok)
 			goto end;
 
 		/* The last error (if any) is still in the error value */
 		ctx->current_issuer=xi;
 		ctx->current_cert=xs;
 		ok=(*cb)(1,ctx);
 		if (!ok) goto end;
 
 		n--;
 		if (n >= 0)
 			{
 			xi=xs;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 	ok=1;
 end:
 	return ok;
 	}
 
 int X509_cmp_current_time(ASN1_TIME *ctm)
 {
 	return X509_cmp_time(ctm, NULL);
 }
 
 int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
-	{
+{
 	char *str;
 	ASN1_TIME atm;
 	long offset;
-	char buff1[24],buff2[24],*p;
-	int i,j;
+    char buff1[24], buff2[24], *p;
+    int i, j, remaining;
 
-	p=buff1;
-	i=ctm->length;
-	str=(char *)ctm->data;
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		if ((i < 11) || (i > 17)) return 0;
-		memcpy(p,str,10);
-		p+=10;
-		str+=10;
+    p = buff1;
+    remaining = ctm->length;
+    str = (char *)ctm->data;
+    /*
+     * Note that the following (historical) code allows much more slack in the
+     * time format than RFC5280. In RFC5280, the representation is fixed:
+     * UTCTime: YYMMDDHHMMSSZ
+     * GeneralizedTime: YYYYMMDDHHMMSSZ
+     */
+    if (ctm->type == V_ASN1_UTCTIME) {
+        /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+        int min_length = sizeof("YYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 10);
+        p += 10;
+        str += 10;
+        remaining -= 10;
+    } else {
+        /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
+        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 12);
+        p += 12;
+        str += 12;
+        remaining -= 12;
 		}
-	else
-		{
-		if (i < 13) return 0;
-		memcpy(p,str,12);
-		p+=12;
-		str+=12;
-		}
 
-	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
-		{ *(p++)='0'; *(p++)='0'; }
-	else
-		{ 
-		*(p++)= *(str++);
-		*(p++)= *(str++);
-		/* Skip any fractional seconds... */
-		if (*str == '.')
-			{
+    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+        *(p++) = '0';
+        *(p++) = '0';
+    } else {
+        /* SS (seconds) */
+        if (remaining < 2)
+            return 0;
+        *(p++) = *(str++);
+        *(p++) = *(str++);
+        remaining -= 2;
+        /*
+         * Skip any (up to three) fractional seconds...
+         * TODO(emilia): in RFC5280, fractional seconds are forbidden.
+         * Can we just kill them altogether?
+         */
+        if (remaining && *str == '.') {
 			str++;
-			while ((*str >= '0') && (*str <= '9')) str++;
+            remaining--;
+            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+                if (*str < '0' || *str > '9')
+                    break;
 			}
-		
 		}
-	*(p++)='Z';
-	*(p++)='\0';
 
-	if (*str == 'Z')
-		offset=0;
-	else
-		{
+    }
+    *(p++) = 'Z';
+    *(p++) = '\0';
+
+    /* We now need either a terminating 'Z' or an offset. */
+    if (!remaining)
+        return 0;
+    if (*str == 'Z') {
+        if (remaining != 1)
+            return 0;
+        offset = 0;
+    } else {
+        /* (+-)HHMM */
 		if ((*str != '+') && (*str != '-'))
 			return 0;
-		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
-		offset+=(str[3]-'0')*10+(str[4]-'0');
+        /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
+        if (remaining != 5)
+            return 0;
+        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+            return 0;
+        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+        offset += (str[3] - '0') * 10 + (str[4] - '0');
 		if (*str == '-')
-			offset= -offset;
+            offset = -offset;
 		}
-	atm.type=ctm->type;
-	atm.length=sizeof(buff2);
-	atm.data=(unsigned char *)buff2;
+    atm.type = ctm->type;
+    atm.length = sizeof(buff2);
+    atm.data = (unsigned char *)buff2;
 
-	if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
 		return 0;
 
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		i=(buff1[0]-'0')*10+(buff1[1]-'0');
-		if (i < 50) i+=100; /* cf. RFC 2459 */
-		j=(buff2[0]-'0')*10+(buff2[1]-'0');
-		if (j < 50) j+=100;
+    if (ctm->type == V_ASN1_UTCTIME) {
+        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+        if (i < 50)
+            i += 100;           /* cf. RFC 2459 */
+        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+        if (j < 50)
+            j += 100;
 
-		if (i < j) return -1;
-		if (i > j) return 1;
+        if (i < j)
+            return -1;
+        if (i > j)
+            return 1;
 		}
-	i=strcmp(buff1,buff2);
+    i = strcmp(buff1, buff2);
 	if (i == 0) /* wait a second then return younger :-) */
 		return -1;
 	else
 		return i;
-	}
+}
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
 	return X509_time_adj(s, adj, NULL);
 }
 
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
 	{
 	time_t t;
 	int type = -1;
 
 	if (in_tm) t = *in_tm;
 	else time(&t);
 
 	t+=adj;
 	if (s) type = s->type;
 	if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t);
 	if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t);
 	return ASN1_TIME_set(s, t);
 	}
 
 int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
 	{
 	EVP_PKEY *ktmp=NULL,*ktmp2;
 	int i,j;
 
 	if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
 
 	for (i=0; i= 0; j--)
 		{
 		ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
 		EVP_PKEY_copy_parameters(ktmp2,ktmp);
 		EVP_PKEY_free(ktmp2);
 		}
 	
 	if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
 	EVP_PKEY_free(ktmp);
 	return 1;
 	}
 
 int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	/* This function is (usually) called only once, by
 	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
 	{
 	return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
 	}
 
 void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
 	{
 	return CRYPTO_get_ex_data(&ctx->ex_data,idx);
 	}
 
 int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
 	{
 	return ctx->error;
 	}
 
 void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
 	{
 	ctx->error=err;
 	}
 
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
 	{
 	return ctx->error_depth;
 	}
 
 X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
 	{
 	return ctx->current_cert;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
 	{
 	return ctx->chain;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
 	{
 	int i;
 	X509 *x;
 	STACK_OF(X509) *chain;
 	if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL;
 	for (i = 0; i < sk_X509_num(chain); i++)
 		{
 		x = sk_X509_value(chain, i);
 		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
 		}
 	return chain;
 	}
 
 void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
 	{
 	ctx->cert=x;
 	}
 
 void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 	{
 	ctx->untrusted=sk;
 	}
 
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 	{
 	ctx->crls=sk;
 	}
 
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
 	}
 
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
 	}
 
 /* This function is used to set the X509_STORE_CTX purpose and trust
  * values. This is intended to be used when another structure has its
  * own trust and purpose values which (if set) will be inherited by
  * the ctx. If they aren't set then we will usually have a default
  * purpose in mind which should then be used to set the trust value.
  * An example of this is SSL use: an SSL structure will have its own
  * purpose and trust settings which the application can set: if they
  * aren't set then we use the default of SSL client/server.
  */
 
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
 				int purpose, int trust)
 {
 	int idx;
 	/* If purpose not set use default */
 	if (!purpose) purpose = def_purpose;
 	/* If we have a purpose then check it is valid */
 	if (purpose)
 		{
 		X509_PURPOSE *ptmp;
 		idx = X509_PURPOSE_get_by_id(purpose);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 			return 0;
 			}
 		ptmp = X509_PURPOSE_get0(idx);
 		if (ptmp->trust == X509_TRUST_DEFAULT)
 			{
 			idx = X509_PURPOSE_get_by_id(def_purpose);
 			if (idx == -1)
 				{
 				X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 				return 0;
 				}
 			ptmp = X509_PURPOSE_get0(idx);
 			}
 		/* If trust not set then get from purpose default */
 		if (!trust) trust = ptmp->trust;
 		}
 	if (trust)
 		{
 		idx = X509_TRUST_get_by_id(trust);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_TRUST_ID);
 			return 0;
 			}
 		}
 
 	if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
 	if (trust && !ctx->param->trust) ctx->param->trust = trust;
 	return 1;
 }
 
 X509_STORE_CTX *X509_STORE_CTX_new(void)
 {
 	X509_STORE_CTX *ctx;
 	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
 	if (!ctx)
 		{
 		X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 	memset(ctx, 0, sizeof(X509_STORE_CTX));
 	return ctx;
 }
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
 	X509_STORE_CTX_cleanup(ctx);
 	OPENSSL_free(ctx);
 }
 
 int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
 	     STACK_OF(X509) *chain)
 	{
 	int ret = 1;
 	ctx->ctx=store;
 	ctx->current_method=0;
 	ctx->cert=x509;
 	ctx->untrusted=chain;
 	ctx->crls = NULL;
 	ctx->last_untrusted=0;
 	ctx->other_ctx=NULL;
 	ctx->valid=0;
 	ctx->chain=NULL;
 	ctx->error=0;
 	ctx->explicit_policy=0;
 	ctx->error_depth=0;
 	ctx->current_cert=NULL;
 	ctx->current_issuer=NULL;
 	ctx->tree = NULL;
 
 	ctx->param = X509_VERIFY_PARAM_new();
 
 	if (!ctx->param)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	/* Inherit callbacks and flags from X509_STORE if not set
 	 * use defaults.
 	 */
 
 
 	if (store)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
 	else
 		ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
 
 	if (store)
 		{
 		ctx->verify_cb = store->verify_cb;
 		ctx->cleanup = store->cleanup;
 		}
 	else
 		ctx->cleanup = 0;
 
 	if (ret)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param,
 					X509_VERIFY_PARAM_lookup("default"));
 
 	if (ret == 0)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	if (store && store->check_issued)
 		ctx->check_issued = store->check_issued;
 	else
 		ctx->check_issued = check_issued;
 
 	if (store && store->get_issuer)
 		ctx->get_issuer = store->get_issuer;
 	else
 		ctx->get_issuer = X509_STORE_CTX_get1_issuer;
 
 	if (store && store->verify_cb)
 		ctx->verify_cb = store->verify_cb;
 	else
 		ctx->verify_cb = null_callback;
 
 	if (store && store->verify)
 		ctx->verify = store->verify;
 	else
 		ctx->verify = internal_verify;
 
 	if (store && store->check_revocation)
 		ctx->check_revocation = store->check_revocation;
 	else
 		ctx->check_revocation = check_revocation;
 
 	if (store && store->get_crl)
 		ctx->get_crl = store->get_crl;
 	else
 		ctx->get_crl = get_crl;
 
 	if (store && store->check_crl)
 		ctx->check_crl = store->check_crl;
 	else
 		ctx->check_crl = check_crl;
 
 	if (store && store->cert_crl)
 		ctx->cert_crl = store->cert_crl;
 	else
 		ctx->cert_crl = cert_crl;
 
 	ctx->check_policy = check_policy;
 
 
 	/* This memset() can't make any sense anyway, so it's removed. As
 	 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
 	 * corresponding "new" here and remove this bogus initialisation. */
 	/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
 	if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
 				&(ctx->ex_data)))
 		{
 		OPENSSL_free(ctx);
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	return 1;
 	}
 
 /* Set alternative lookup method: just a STACK of trusted certificates.
  * This avoids X509_STORE nastiness where it isn't needed.
  */
 
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
 	ctx->other_ctx = sk;
 	ctx->get_issuer = get_issuer_sk;
 }
 
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
 	{
 	if (ctx->cleanup) ctx->cleanup(ctx);
 	if (ctx->param != NULL)
 		{
 		X509_VERIFY_PARAM_free(ctx->param);
 		ctx->param=NULL;
 		}
 	if (ctx->tree != NULL)
 		{
 		X509_policy_tree_free(ctx->tree);
 		ctx->tree=NULL;
 		}
 	if (ctx->chain != NULL)
 		{
 		sk_X509_pop_free(ctx->chain,X509_free);
 		ctx->chain=NULL;
 		}
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
 	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
 	}
 
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
 	{
 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
 	}
 
 void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
 	{
 	X509_VERIFY_PARAM_set_flags(ctx->param, flags);
 	}
 
 void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
 	{
 	X509_VERIFY_PARAM_set_time(ctx->param, t);
 	}
 
 void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
 				  int (*verify_cb)(int, X509_STORE_CTX *))
 	{
 	ctx->verify_cb=verify_cb;
 	}
 
 X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
 	{
 	return ctx->tree;
 	}
 
 int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
 	{
 	return ctx->explicit_policy;
 	}
 
 int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
 	{
 	const X509_VERIFY_PARAM *param;
 	param = X509_VERIFY_PARAM_lookup(name);
 	if (!param)
 		return 0;
 	return X509_VERIFY_PARAM_inherit(ctx->param, param);
 	}
 
 X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
 	{
 	return ctx->param;
 	}
 
 void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
 	{
 	if (ctx->param)
 		X509_VERIFY_PARAM_free(ctx->param);
 	ctx->param = param;
 	}
 
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)
 
 IMPLEMENT_STACK_OF(X509_NAME)
 
 IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
 IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
Index: releng/8.4/crypto/openssl/ssl/d1_lib.c
===================================================================
--- releng/8.4/crypto/openssl/ssl/d1_lib.c	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/d1_lib.c	(revision 284295)
@@ -1,518 +1,521 @@
 /* ssl/d1_lib.c */
 /* 
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  */
 /* ====================================================================
  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 #define USE_SOCKETS
 #include 
 #include "ssl_locl.h"
 
 #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
 #include 
 #endif
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
 int dtls1_listen(SSL *s, struct sockaddr *client);
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
 	tls1_mac,
 	tls1_setup_key_block,
 	tls1_generate_master_secret,
 	tls1_change_cipher_state,
 	tls1_final_finish_mac,
 	TLS1_FINISH_MAC_LENGTH,
 	tls1_cert_verify_mac,
 	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
 	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
 	tls1_alert_code,
 	};
 
 long dtls1_default_timeout(void)
 	{
 	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec
 	 * is way too long for http, the cache would over fill */
 	return(60*60*2);
 	}
 
 IMPLEMENT_dtls1_meth_func(dtlsv1_base_method,
 			ssl_undefined_function,
 			ssl_undefined_function,
 			ssl_bad_method)
 
 int dtls1_new(SSL *s)
 	{
 	DTLS1_STATE *d1;
 
 	if (!ssl3_new(s)) return(0);
 	if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0);
 	memset(d1,0, sizeof *d1);
 
 	/* d1->handshake_epoch=0; */
 #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST)
 	d1->bitmap.length=64;
 #else
 	d1->bitmap.length=sizeof(d1->bitmap.map) * 8;
 #endif
 	pq_64bit_init(&(d1->bitmap.map));
 	pq_64bit_init(&(d1->bitmap.max_seq_num));
 	
 	d1->next_bitmap.length = d1->bitmap.length;
 	pq_64bit_init(&(d1->next_bitmap.map));
 	pq_64bit_init(&(d1->next_bitmap.max_seq_num));
 
 	d1->unprocessed_rcds.q=pqueue_new();
 	d1->processed_rcds.q=pqueue_new();
 	d1->buffered_messages = pqueue_new();
 	d1->sent_messages=pqueue_new();
 	d1->buffered_app_data.q=pqueue_new();
 
 	if ( s->server)
 		{
 		d1->cookie_len = sizeof(s->d1->cookie);
 		}
 
 	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
         || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
 		{
         if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
         if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
         if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
 		if ( d1->sent_messages) pqueue_free(d1->sent_messages);
 		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
 		OPENSSL_free(d1);
 		return (0);
 		}
 
 	s->d1=d1;
 	s->method->ssl_clear(s);
 	return(1);
 	}
 
 static void dtls1_clear_queues(SSL *s)
 	{
     pitem *item = NULL;
     hm_fragment *frag = NULL;
 	DTLS1_RECORD_DATA *rdata;
 
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         OPENSSL_free(frag->fragment);
         OPENSSL_free(frag);
         pitem_free(item);
         }
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         OPENSSL_free(frag->fragment);
         OPENSSL_free(frag);
         pitem_free(item);
         }
 
 	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
 		{
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
 		OPENSSL_free(item->data);
 		pitem_free(item);
 		}
 	}
 
 void dtls1_free(SSL *s)
 	{
 	ssl3_free(s);
 
 	dtls1_clear_queues(s);
 
     pqueue_free(s->d1->unprocessed_rcds.q);
     pqueue_free(s->d1->processed_rcds.q);
     pqueue_free(s->d1->buffered_messages);
 	pqueue_free(s->d1->sent_messages);
 	pqueue_free(s->d1->buffered_app_data.q);
 	
 	pq_64bit_free(&(s->d1->bitmap.map));
 	pq_64bit_free(&(s->d1->bitmap.max_seq_num));
 
 	pq_64bit_free(&(s->d1->next_bitmap.map));
 	pq_64bit_free(&(s->d1->next_bitmap.max_seq_num));
 
 	OPENSSL_free(s->d1);
 	s->d1 = NULL;
 	}
 
 void dtls1_clear(SSL *s)
 	{
     pqueue unprocessed_rcds;
     pqueue processed_rcds;
     pqueue buffered_messages;
 	pqueue sent_messages;
 	pqueue buffered_app_data;
 	unsigned int mtu;
 
 	if (s->d1)
 		{
 		unprocessed_rcds = s->d1->unprocessed_rcds.q;
 		processed_rcds = s->d1->processed_rcds.q;
 		buffered_messages = s->d1->buffered_messages;
 		sent_messages = s->d1->sent_messages;
 		buffered_app_data = s->d1->buffered_app_data.q;
 		mtu = s->d1->mtu;
 
 		dtls1_clear_queues(s);
 
 		pq_64bit_free(&(s->d1->bitmap.map));
 		pq_64bit_free(&(s->d1->bitmap.max_seq_num));
 
 		pq_64bit_free(&(s->d1->next_bitmap.map));
 		pq_64bit_free(&(s->d1->next_bitmap.max_seq_num));
 
 		memset(s->d1, 0, sizeof(*(s->d1)));
 
 		if (s->server)
 			{
 			s->d1->cookie_len = sizeof(s->d1->cookie);
 			}
 
 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
 			{
 			s->d1->mtu = mtu;
 			}
 
 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
 		s->d1->processed_rcds.q = processed_rcds;
 		s->d1->buffered_messages = buffered_messages;
 		s->d1->sent_messages = sent_messages;
 		s->d1->buffered_app_data.q = buffered_app_data;
 
 #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST)
 		s->d1->bitmap.length=64;
 #else
 		s->d1->bitmap.length=sizeof(s->d1->bitmap.map) * 8;
 #endif
 		pq_64bit_init(&(s->d1->bitmap.map));
 		pq_64bit_init(&(s->d1->bitmap.max_seq_num));
 		
 		s->d1->next_bitmap.length = s->d1->bitmap.length;
 		pq_64bit_init(&(s->d1->next_bitmap.map));
 		pq_64bit_init(&(s->d1->next_bitmap.max_seq_num));
 		}
 
 	ssl3_clear(s);
 	if (s->options & SSL_OP_CISCO_ANYCONNECT)
 		s->version=DTLS1_BAD_VER;
 	else
 		s->version=DTLS1_VERSION;
 	}
 
 long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
 	{
 	int ret=0;
 
 	switch (cmd)
 		{
 	case DTLS_CTRL_GET_TIMEOUT:
 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
 			{
 			ret = 1;
 			}
 		break;
 	case DTLS_CTRL_HANDLE_TIMEOUT:
 		ret = dtls1_handle_timeout(s);
 		break;
 	case DTLS_CTRL_LISTEN:
 		ret = dtls1_listen(s, parg);
 		break;
 	case SSL_CTRL_CHECK_PROTO_VERSION:
 		/* For library-internal use; checks that the current protocol
 		 * is the highest enabled version (according to s->ctx->method,
 		 * as version negotiation may have changed s->method). */
 #if DTLS_MAX_VERSION != DTLS1_VERSION
 #  error Code needs update for DTLS_method() support beyond DTLS1_VERSION.
 #endif
 		/* Just one protocol version is supported so far;
 		 * fail closed if the version is not as expected. */
 		return s->version == DTLS_MAX_VERSION;
 
 	default:
 		ret = ssl3_ctrl(s, cmd, larg, parg);
 		break;
 		}
 	return(ret);
 	}
 
 /*
  * As it's impossible to use stream ciphers in "datagram" mode, this
  * simple filter is designed to disengage them in DTLS. Unfortunately
  * there is no universal way to identify stream SSL_CIPHER, so we have
  * to explicitly list their SSL_* codes. Currently RC4 is the only one
  * available, but if new ones emerge, they will have to be added...
  */
 SSL_CIPHER *dtls1_get_cipher(unsigned int u)
 	{
 	SSL_CIPHER *ciph = ssl3_get_cipher(u);
 
 	if (ciph != NULL)
 		{
 		if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4)
 			return NULL;
 		}
 
 	return ciph;
 	}
 
 void dtls1_start_timer(SSL *s)
 	{
 	/* If timer is not set, initialize duration with 1 second */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		s->d1->timeout_duration = 1;
 		}
 	
 	/* Set timeout to current time */
 	get_current_time(&(s->d1->next_timeout));
 
 	/* Add duration to current time */
 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	}
 
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
 	{
 	struct timeval timenow;
 
 	/* If no timeout is set, just return NULL */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		return NULL;
 		}
 
 	/* Get current time */
 	get_current_time(&timenow);
 
 	/* If timer already expired, set remaining time to 0 */
 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
 		(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
 		 s->d1->next_timeout.tv_usec <= timenow.tv_usec))
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		return timeleft;
 		}
 
 	/* Calculate time left until timer expires */
 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
 	timeleft->tv_sec -= timenow.tv_sec;
 	timeleft->tv_usec -= timenow.tv_usec;
 	if (timeleft->tv_usec < 0)
 		{
 		timeleft->tv_sec--;
 		timeleft->tv_usec += 1000000;
 		}
 
 	/* If remaining time is less than 15 ms, set it to 0
 	 * to prevent issues because of small devergences with
 	 * socket timeouts.
 	 */
 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		}
 	
 
 	return timeleft;
 	}
 
 int dtls1_is_timer_expired(SSL *s)
 	{
 	struct timeval timeleft;
 
 	/* Get time left until timeout, return false if no timer running */
 	if (dtls1_get_timeout(s, &timeleft) == NULL)
 		{
 		return 0;
 		}
 
 	/* Return false if timer is not expired yet */
 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
 		{
 		return 0;
 		}
 
 	/* Timer expired, so return true */	
 	return 1;
 	}
 
 void dtls1_double_timeout(SSL *s)
 	{
 	s->d1->timeout_duration *= 2;
 	if (s->d1->timeout_duration > 60)
 		s->d1->timeout_duration = 60;
 	dtls1_start_timer(s);
 	}
 
 void dtls1_stop_timer(SSL *s)
 	{
 	/* Reset everything */
 	memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
 	s->d1->timeout_duration = 1;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	/* Clear retransmission buffer */
 	dtls1_clear_record_buffer(s);
 	}
 
 int dtls1_check_timeout_num(SSL *s)
 	{
 	s->d1->timeout.num_alerts++;
 
 	/* Reduce MTU after 2 unsuccessful retransmissions */
 	if (s->d1->timeout.num_alerts > 2)
 		{
 		s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);		
 		}
 
 	if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
 		{
 		/* fail the connection, enough alerts have been sent */
 		SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM,SSL_R_READ_TIMEOUT_EXPIRED);
 		return -1;
 		}
 
 	return 0;
 	}
 
 int dtls1_handle_timeout(SSL *s)
 	{
 	/* if no timer is expired, don't do anything */
 	if (!dtls1_is_timer_expired(s))
 		{
 		return 0;
 		}
 
 	dtls1_double_timeout(s);
 
 	if (dtls1_check_timeout_num(s) < 0)
 		return -1;
 
 	s->d1->timeout.read_timeouts++;
 	if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
 		{
 		s->d1->timeout.read_timeouts = 1;
 		}
 
 	dtls1_start_timer(s);
 	return dtls1_retransmit_buffered_messages(s);
 	}
 
 static void get_current_time(struct timeval *t)
 {
 #ifdef OPENSSL_SYS_WIN32
 	struct _timeb tb;
 	_ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #elif defined(OPENSSL_SYS_VMS)
 	struct timeb tb;
 	ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #else
 	gettimeofday(t, NULL);
 #endif
 }
 
 int dtls1_listen(SSL *s, struct sockaddr *client)
 	{
 	int ret;
 
+	/* Ensure there is no state left over from a previous invocation */
+	SSL_clear(s);
+
 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
 	s->d1->listen = 1;
 
 	ret = SSL_accept(s);
 	if (ret <= 0) return ret;
 	
 	(void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
 	return 1;
 	}
Index: releng/8.4/crypto/openssl/ssl/s3_clnt.c
===================================================================
--- releng/8.4/crypto/openssl/ssl/s3_clnt.c	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/s3_clnt.c	(revision 284295)
@@ -1,2868 +1,2900 @@
 /* ssl/s3_clnt.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifdef OPENSSL_FIPS
 #include 
 #endif
 
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 
 static SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 
 #ifndef OPENSSL_NO_ECDH
 static int curve_id2nid(int curve_id);
 int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
 #endif
 
 static SSL_METHOD *ssl3_get_client_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_client_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
 			ssl_undefined_function,
 			ssl3_connect,
 			ssl3_get_client_method)
 
 int ssl3_connect(SSL *s)
 	{
 	BUF_MEM *buf=NULL;
 	unsigned long Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 	
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch(s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->new_session=1;
 			s->state=SSL_ST_CONNECT;
 			s->ctx->stats.sess_connect_renegotiate++;
 			/* break */
 		case SSL_ST_BEFORE:
 		case SSL_ST_CONNECT:
 		case SSL_ST_BEFORE|SSL_ST_CONNECT:
 		case SSL_ST_OK|SSL_ST_CONNECT:
 
 			s->server=0;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version & 0xff00 ) != 0x0300)
 				{
 				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
 				ret = -1;
 				goto end;
 				}
 				
 			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_CONNECT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				buf=NULL;
 				}
 
 			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
 
 			/* setup buffing BIO */
 			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
 
 			/* don't push the buffering BIO quite yet */
 
 			ssl3_init_finished_mac(s);
 
 			s->state=SSL3_ST_CW_CLNT_HELLO_A;
 			s->ctx->stats.sess_connect++;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CLNT_HELLO_A:
 		case SSL3_ST_CW_CLNT_HELLO_B:
 
 			s->shutdown=0;
 			ret=ssl3_client_hello(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_HELLO_A;
 			s->init_num=0;
 
 			/* turn on buffering for the next lot of output */
 			if (s->bbio != s->wbio)
 				s->wbio=BIO_push(s->bbio,s->wbio);
 
 			break;
 
 		case SSL3_ST_CR_SRVR_HELLO_A:
 		case SSL3_ST_CR_SRVR_HELLO_B:
 			ret=ssl3_get_server_hello(s);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				{
 				s->state=SSL3_ST_CR_FINISHED_A;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_ticket_expected)
 					{
 					/* receive renewed session ticket */
 					s->state=SSL3_ST_CR_SESSION_TICKET_A;
 					}
 #endif
 				}
 			else
 				s->state=SSL3_ST_CR_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_CERT_A:
 		case SSL3_ST_CR_CERT_B:
 #ifndef OPENSSL_NO_TLSEXT
 			ret=ssl3_check_finished(s);
 			if (ret <= 0) goto end;
 			if (ret == 2)
 				{
 				s->hit = 1;
 				if (s->tlsext_ticket_expected)
 					s->state=SSL3_ST_CR_SESSION_TICKET_A;
 				else
 					s->state=SSL3_ST_CR_FINISHED_A;
 				s->init_num=0;
 				break;
 				}
 #endif
 			/* Check if it is anon DH/ECDH */
 			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
 				{
 				ret=ssl3_get_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_CR_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_KEY_EXCH_A:
 		case SSL3_ST_CR_KEY_EXCH_B:
 			ret=ssl3_get_key_exchange(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_CERT_REQ_A;
 			s->init_num=0;
 
 			/* at this point we check that we have the
 			 * required stuff from the server */
 			if (!ssl3_check_cert_and_algorithm(s))
 				{
 				ret= -1;
 				goto end;
 				}
 			break;
 
 		case SSL3_ST_CR_CERT_REQ_A:
 		case SSL3_ST_CR_CERT_REQ_B:
 			ret=ssl3_get_certificate_request(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_DONE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_SRVR_DONE_A:
 		case SSL3_ST_CR_SRVR_DONE_B:
 			ret=ssl3_get_server_done(s);
 			if (ret <= 0) goto end;
 			if (s->s3->tmp.cert_req)
 				s->state=SSL3_ST_CW_CERT_A;
 			else
 				s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 
 			break;
 
 		case SSL3_ST_CW_CERT_A:
 		case SSL3_ST_CW_CERT_B:
 		case SSL3_ST_CW_CERT_C:
 		case SSL3_ST_CW_CERT_D:
 			ret=ssl3_send_client_certificate(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_KEY_EXCH_A:
 		case SSL3_ST_CW_KEY_EXCH_B:
 			ret=ssl3_send_client_key_exchange(s);
 			if (ret <= 0) goto end;
 			/* EAY EAY EAY need to check for DH fix cert
 			 * sent back */
 			/* For TLS, cert_req is set to 2, so a cert chain
 			 * of nothing is sent, but no verify packet is sent */
 			/* XXX: For now, we do not support client 
 			 * authentication in ECDH cipher suites with
 			 * ECDH (rather than ECDSA) certificates.
 			 * We need to skip the certificate verify 
 			 * message when client's ECDH public key is sent 
 			 * inside the client certificate.
 			 */
 			if (s->s3->tmp.cert_req == 1)
 				{
 				s->state=SSL3_ST_CW_CERT_VRFY_A;
 				}
 			else
 				{
 				s->state=SSL3_ST_CW_CHANGE_A;
 				s->s3->change_cipher_spec=0;
 				}
 
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CERT_VRFY_A:
 		case SSL3_ST_CW_CERT_VRFY_B:
 			ret=ssl3_send_client_verify(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_CHANGE_A;
 			s->init_num=0;
 			s->s3->change_cipher_spec=0;
 			break;
 
 		case SSL3_ST_CW_CHANGE_A:
 		case SSL3_ST_CW_CHANGE_B:
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_FINISHED_A;
 			s->init_num=0;
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 #ifdef OPENSSL_NO_COMP
 			s->session->compress_meth=0;
 #else
 			if (s->s3->tmp.new_compression == NULL)
 				s->session->compress_meth=0;
 			else
 				s->session->compress_meth=
 					s->s3->tmp.new_compression->id;
 #endif
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 		case SSL3_ST_CW_FINISHED_A:
 		case SSL3_ST_CW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
 				s->method->ssl3_enc->client_finished_label,
 				s->method->ssl3_enc->client_finished_label_len);
 			if (ret <= 0) goto end;
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			s->state=SSL3_ST_CW_FLUSH;
 
 			/* clear flags */
 			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
 			if (s->hit)
 				{
 				s->s3->tmp.next_state=SSL_ST_OK;
 				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
 					{
 					s->state=SSL_ST_OK;
 					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
 					s->s3->delay_buf_pop_ret=0;
 					}
 				}
 			else
 				{
 #ifndef OPENSSL_NO_TLSEXT
 				/* Allow NewSessionTicket if ticket expected */
 				if (s->tlsext_ticket_expected)
 					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
 				else
 #endif
 				
 				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
 				}
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_CR_SESSION_TICKET_A:
 		case SSL3_ST_CR_SESSION_TICKET_B:
 			ret=ssl3_get_new_session_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_FINISHED_A;
 			s->init_num=0;
 		break;
 
 		case SSL3_ST_CR_CERT_STATUS_A:
 		case SSL3_ST_CR_CERT_STATUS_B:
 			ret=ssl3_get_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 			s->init_num=0;
 		break;
 #endif
 
 		case SSL3_ST_CR_FINISHED_A:
 		case SSL3_ST_CR_FINISHED_B:
 
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
 				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
 
 			if (s->hit)
 				s->state=SSL3_ST_CW_CHANGE_A;
 			else
 				s->state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_FLUSH:
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			if (s->init_buf != NULL)
 				{
 				BUF_MEM_free(s->init_buf);
 				s->init_buf=NULL;
 				}
 
 			/* If we are not 'joining' the last two packets,
 			 * remove the buffering now */
 			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
 				ssl_free_wbio_buffer(s);
 			/* else do it later in ssl3_write */
 
 			s->init_num=0;
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
 			if (s->hit) s->ctx->stats.sess_hit++;
 
 			ret=1;
 			/* s->server=0; */
 			s->handshake_func=ssl3_connect;
 			s->ctx->stats.sess_connect_good++;
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 
 			goto end;
 			/* break; */
 			
 		default:
 			SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 
 		/* did we do anything */
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_CONNECT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	s->in_handshake--;
 	if (buf != NULL)
 		BUF_MEM_free(buf);
 	if (cb != NULL)
 		cb(s,SSL_CB_CONNECT_EXIT,ret);
 	return(ret);
 	}
 
 
 int ssl3_client_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i;
 	unsigned long Time,l;
 #ifndef OPENSSL_NO_COMP
 	int j;
 	SSL_COMP *comp;
 #endif
 
 	buf=(unsigned char *)s->init_buf->data;
 	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
 		{
 		SSL_SESSION *sess = s->session;
 		if ((sess == NULL) ||
 			(sess->ssl_version != s->version) ||
 #ifdef OPENSSL_NO_TLSEXT
 			!sess->session_id_length ||
 #else
 			(!sess->session_id_length && !sess->tlsext_tick) ||
 #endif
 			(sess->not_resumable))
 			{
 			if (!ssl_get_new_session(s,0))
 				goto err;
 			}
 		/* else use the pre-loaded session */
 
 		p=s->s3->client_random;
 		Time=(unsigned long)time(NULL);			/* Time */
 		l2n(Time,p);
 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
 			goto err;
 
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 		s->client_version=s->version;
 
 		/* Random stuff */
 		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* Session ID */
 		if (s->new_session)
 			i=0;
 		else
 			i=s->session->session_id_length;
 		*(p++)=i;
 		if (i != 0)
 			{
 			if (i > (int)sizeof(s->session->session_id))
 				{
 				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			memcpy(p,s->session->session_id,i);
 			p+=i;
 			}
 		
 		/* Ciphers supported */
 		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
 			goto err;
 			}
 		s2n(i,p);
 		p+=i;
 
 		/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 		*(p++)=1;
 #else
 		if (s->ctx->comp_methods == NULL)
 			j=0;
 		else
 			j=sk_SSL_COMP_num(s->ctx->comp_methods);
 		*(p++)=1+j;
 		for (i=0; ictx->comp_methods,i);
 			*(p++)=comp->id;
 			}
 #endif
 		*(p++)=0; /* Add the NULL method */
 #ifndef OPENSSL_NO_TLSEXT
 		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 #endif		
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_CLIENT_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_CW_CLNT_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_CLNT_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_server_hello(SSL *s)
 	{
 	STACK_OF(SSL_CIPHER) *sk;
 	SSL_CIPHER *c;
 	unsigned char *p,*d;
 	int i,al,ok;
 	unsigned int j;
 	long n;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp;
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_HELLO_A,
 		SSL3_ST_CR_SRVR_HELLO_B,
 		-1,
 		20000, /* ?? */
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
 		{
 		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
 			{
 			if ( s->d1->send_cookie == 0)
 				{
 				s->s3->tmp.reuse_message = 1;
 				return 1;
 				}
 			else /* already sent a cookie */
 				{
 				al=SSL_AD_UNEXPECTED_MESSAGE;
 				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 				goto f_err;
 				}
 			}
 		}
 	
 	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 
 	d=p=(unsigned char *)s->init_msg;
 
 	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
 		s->version=(s->version&0xff00)|p[1];
 		al=SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 	p+=2;
 
 	/* load the server hello data */
 	/* load the server random */
 	memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	/* get the session-id */
 	j= *(p++);
 
 	if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG);
 		goto f_err;
 		}
 
 	if (j != 0 && j == s->session->session_id_length
 	    && memcmp(p,s->session->session_id,j) == 0)
 	    {
 	    if(s->sid_ctx_length != s->session->sid_ctx_length
 	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length))
 		{
 		/* actually a client application bug */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 		goto f_err;
 		}
 	    s->s3->flags |= SSL3_FLAGS_CCS_OK;
 	    s->hit=1;
 	    }
 	else	/* a miss or crap from the other end */
 		{
 		/* If we were trying for session-id reuse, make a new
 		 * SSL_SESSION so we don't stuff up other people */
 		s->hit=0;
 		if (s->session->session_id_length > 0)
 			{
 			if (!ssl_get_new_session(s,0))
 				{
 				al=SSL_AD_INTERNAL_ERROR;
 				goto f_err;
 				}
 			}
 		s->session->session_id_length=j;
 		memcpy(s->session->session_id,p,j); /* j could be 0 */
 		}
 	p+=j;
 	c=ssl_get_cipher_by_char(s,p);
 	if (c == NULL)
 		{
 		/* unknown cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
 		goto f_err;
 		}
 	p+=ssl_put_cipher_by_char(s,NULL,NULL);
 
 	sk=ssl_get_ciphers_by_id(s);
 	i=sk_SSL_CIPHER_find(sk,c);
 	if (i < 0)
 		{
 		/* we did not say we would use this cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
 		goto f_err;
 		}
 
 	/* Depending on the session caching (internal/external), the cipher
 	   and/or cipher_id values may not be set. Make sure that
 	   cipher_id is set and use it for comparison. */
 	if (s->session->cipher)
 		s->session->cipher_id = s->session->cipher->id;
 	if (s->hit && (s->session->cipher_id != c->id))
 		{
 /* Workaround is now obsolete */
 #if 0
 		if (!(s->options &
 			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
 #endif
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
 			goto f_err;
 			}
 		}
 	s->s3->tmp.new_cipher=c;
 
 	/* lets get the compression algorithm */
 	/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 	if (*(p++) != 0)
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 #else
 	j= *(p++);
 	if (j == 0)
 		comp=NULL;
 	else
 		comp=ssl3_comp_find(s->ctx->comp_methods,j);
 	
 	if ((j != 0) && (comp == NULL))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 	else
 		{
 		s->s3->tmp.new_compression=comp;
 		}
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_serverhello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err; 
 			}
 		if (ssl_check_serverhello_tlsext(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
 				goto err;
 			}
 		}
 #endif
 
 
 	if (p != (d+n))
 		{
 		/* wrong packet length */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 #ifndef OPENSSL_NO_TLSEXT
 err:
 #endif
 	return(-1);
 	}
 
 int ssl3_get_server_certificate(SSL *s)
 	{
 	int al,i,ok,ret= -1;
 	unsigned long n,nc,llen,l;
 	X509 *x=NULL;
 	const unsigned char *q,*p;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 	SESS_CERT *sc;
 	EVP_PKEY *pkey=NULL;
 	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_A,
 		SSL3_ST_CR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
 		((s->s3->tmp.new_cipher->algorithms & SSL_aKRB5) && 
 		(s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&q,l);
 		if (x == NULL)
 			{
 			al=SSL_AD_BAD_CERTIFICATE;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto f_err;
 			}
 		if (q != (p+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		p=q;
 		}
 
 	i=ssl_verify_cert_chain(s,sk);
 	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
 #ifndef OPENSSL_NO_KRB5
 	        && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
 	        != (SSL_aKRB5|SSL_kKRB5)
 #endif /* OPENSSL_NO_KRB5 */
 	        )
 		{
 		al=ssl_verify_alarm_type(s->verify_result);
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
 		goto f_err; 
 		}
 	ERR_clear_error(); /* but we keep s->verify_result */
 
 	sc=ssl_sess_cert_new();
 	if (sc == NULL) goto err;
 
 	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
 	s->session->sess_cert=sc;
 
 	sc->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does include the peer's
 	 * certificate, which we don't include in s3_srvr.c */
 	x=sk_X509_value(sk,0);
 	sk=NULL;
  	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
 
 	pkey=X509_get_pubkey(x);
 
 	/* VRS: allow null cert if auth == KRB5 */
 	need_cert =	((s->s3->tmp.new_cipher->algorithms
 	                 & (SSL_MKEY_MASK|SSL_AUTH_MASK))
 	                 == (SSL_aKRB5|SSL_kKRB5))? 0: 1;
 
 #ifdef KSSL_DEBUG
 	printf("pkey,x = %p, %p\n", (void *)pkey,(void *)x);
 	printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
 	printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name,
 	        s->s3->tmp.new_cipher->algorithms, need_cert);
 #endif    /* KSSL_DEBUG */
 
 	if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
 		goto f_err;
 		}
 
 	i=ssl_cert_type(x,pkey);
 	if (need_cert && i < 0)
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNKNOWN_CERTIFICATE_TYPE);
 		goto f_err;
 		}
 
 	if (need_cert)
 		{
 		sc->peer_cert_type=i;
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		/* Why would the following ever happen?
 		 * We just created sc a couple of lines ago. */
 		if (sc->peer_pkeys[i].x509 != NULL)
 			X509_free(sc->peer_pkeys[i].x509);
 		sc->peer_pkeys[i].x509=x;
 		sc->peer_key= &(sc->peer_pkeys[i]);
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		s->session->peer=x;
 		}
 	else
 		{
 		sc->peer_cert_type=i;
 		sc->peer_key= NULL;
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		s->session->peer=NULL;
 		}
 	s->session->verify_result = s->verify_result;
 
 	x=NULL;
 	ret=1;
 
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	EVP_PKEY_free(pkey);
 	X509_free(x);
 	sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_get_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
 #endif
 	EVP_MD_CTX md_ctx;
 	unsigned char *param,*p;
 	int al,j,ok;
 	long i,param_len,n,alg;
 	EVP_PKEY *pkey=NULL;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh = NULL;
 	BN_CTX *bn_ctx = NULL;
 	EC_POINT *srvr_ecpoint = NULL;
 	int curve_nid = 0;
 	int encoded_pt_len = 0;
 #endif
 
 	/* use same message size as in ssl3_get_certificate_request()
 	 * as ServerKeyExchange message may be skipped */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_KEY_EXCH_A,
 		SSL3_ST_CR_KEY_EXCH_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	alg=s->s3->tmp.new_cipher->algorithms;
 	EVP_MD_CTX_init(&md_ctx);
 
 	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
 		{
 		/*
 		 * Can't skip server key exchange if this is an ephemeral
 		 * ciphersuite.
 		 */
 		if (alg & (SSL_kEDH|SSL_kECDHE))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
 			al = SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	param=p=(unsigned char *)s->init_msg;
 
 	if (s->session->sess_cert != NULL)
 		{
 #ifndef OPENSSL_NO_RSA
 		if (s->session->sess_cert->peer_rsa_tmp != NULL)
 			{
 			RSA_free(s->session->sess_cert->peer_rsa_tmp);
 			s->session->sess_cert->peer_rsa_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		if (s->session->sess_cert->peer_dh_tmp)
 			{
 			DH_free(s->session->sess_cert->peer_dh_tmp);
 			s->session->sess_cert->peer_dh_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->session->sess_cert->peer_ecdh_tmp)
 			{
 			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
 			s->session->sess_cert->peer_ecdh_tmp=NULL;
 			}
 #endif
 		}
 	else
 		{
 		s->session->sess_cert=ssl_sess_cert_new();
 		}
 
 	/* Total length of the parameters including the length prefix */
 	param_len=0;
 
 	al=SSL_AD_DECODE_ERROR;
 #ifndef OPENSSL_NO_RSA
 	if (alg & SSL_kRSA)
 		{
 		/* Temporary RSA keys only allowed in export ciphersuites */
 		if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher))
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
 		if ((rsa=RSA_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 		/* this should be because we are using an export cipher */
 		if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 		else
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		s->session->sess_cert->peer_rsa_tmp=rsa;
 		rsa=NULL;
 		}
 #else /* OPENSSL_NO_RSA */
 	if (0)
 		;
 #endif
 #ifndef OPENSSL_NO_DH
 	else if (alg & SSL_kEDH)
 		{
 		if ((dh=DH_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->p=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->g=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 #ifndef OPENSSL_NO_RSA
 		if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #else
 		if (0)
 			;
 #endif
 #ifndef OPENSSL_NO_DSA
 		else if (alg & SSL_aDSS)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
 #endif
 		/* else anonymous DH, so no certificate or pkey. */
 
 		s->session->sess_cert->peer_dh_tmp=dh;
 		dh=NULL;
 		}
 	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_DH */
 
 #ifndef OPENSSL_NO_ECDH
 	else if (alg & SSL_kECDHE)
 		{
 		EC_GROUP *ngroup;
 		const EC_GROUP *group;
 
 		if ((ecdh=EC_KEY_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		/* Extract elliptic curve parameters and the
 		 * server's ephemeral ECDH public key.
 		 * Keep accumulating lengths of various components in
 		 * param_len and make sure it never exceeds n.
 		 */
 
 		/* XXX: For now we only support named (not generic) curves
 		 * and the ECParameters in this case is just three bytes. We
 		 * also need one byte for the length of the encoded point
 		 */
 		param_len=4;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 
 		if ((*p != NAMED_CURVE_TYPE) || 
 		    ((curve_nid = curve_id2nid(*(p + 2))) == 0))
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
 			goto f_err;
 			}
 
 		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
 		if (ngroup == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_KEY_set_group(ecdh, ngroup) == 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		EC_GROUP_free(ngroup);
 
 		group = EC_KEY_get0_group(ecdh);
 
 		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 		    (EC_GROUP_get_degree(group) > 163))
 			{
 			al=SSL_AD_EXPORT_RESTRICTION;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 			goto f_err;
 			}
 
 		p+=3;
 
 		/* Next, get the encoded ECPoint */
 		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
 		    ((bn_ctx = BN_CTX_new()) == NULL))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		encoded_pt_len = *p;  /* length of encoded point */
 		p+=1;
 
 		if ((encoded_pt_len > n - param_len) ||
 		    (EC_POINT_oct2point(group, srvr_ecpoint, 
 			p, encoded_pt_len, bn_ctx) == 0))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
 			goto f_err;
 			}
 		param_len += encoded_pt_len;
 
 		n-=param_len;
 		p+=encoded_pt_len;
 
 		/* The ECC/TLS specification does not mention
 		 * the use of DSA to sign ECParameters in the server
 		 * key exchange message. We do support RSA and ECDSA.
 		 */
 		if (0) ;
 #ifndef OPENSSL_NO_RSA
 		else if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		else if (alg & SSL_aECDSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 #endif
 		/* else anonymous ECDH, so no certificate or pkey. */
 		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
 		s->session->sess_cert->peer_ecdh_tmp=ecdh;
 		ecdh=NULL;
 		BN_CTX_free(bn_ctx);
 		bn_ctx = NULL;
 		EC_POINT_free(srvr_ecpoint);
 		srvr_ecpoint = NULL;
 		}
 	else if (alg & SSL_kECDH)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_ECDH */
 	if (alg & SSL_aFZA)
 		{
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
 
 
 	/* p points to the next byte, there are 'n' bytes left */
 
 	/* if it was signed, check the signature */
 	if (pkey != NULL)
 		{
 		n2s(p,i);
 		n-=2;
 		j=EVP_PKEY_size(pkey);
 
 		/* Check signature length. If n is 0 then signature is empty */
 		if ((i != n) || (n > j) || (n <= 0))
 			{
 			/* wrong packet length */
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
 			goto f_err;
 			}
 
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA)
 			{
 			int num;
 			unsigned int size;
 
 			j=0;
 			q=md_buf;
 			for (num=2; num > 0; num--)
 				{
 				EVP_MD_CTX_set_flags(&md_ctx,
 					EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 				EVP_DigestInit_ex(&md_ctx,(num == 2)
 					?s->ctx->md5:s->ctx->sha1, NULL);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,param,param_len);
 				EVP_DigestFinal_ex(&md_ctx,q,&size);
 				q+=size;
 				j+=size;
 				}
 			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
 								pkey->pkey.rsa);
 			if (i < 0)
 				{
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
 				goto f_err;
 				}
 			if (i == 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DSA
 			if (pkey->type == EVP_PKEY_DSA)
 			{
 			/* lets do DSS */
 			EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
 			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			if (pkey->type == EVP_PKEY_EC)
 			{
 			/* let's do ECDSA */
 			EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
 			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	else
 		{
 		/* still data left over */
 		if (!(alg & SSL_aNULL))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		if (n != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
 			goto f_err;
 			}
 		}
 	EVP_PKEY_free(pkey);
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	EVP_PKEY_free(pkey);
 #ifndef OPENSSL_NO_RSA
 	if (rsa != NULL)
 		RSA_free(rsa);
 #endif
 #ifndef OPENSSL_NO_DH
 	if (dh != NULL)
 		DH_free(dh);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	EC_POINT_free(srvr_ecpoint);
 	if (ecdh != NULL)
 		EC_KEY_free(ecdh);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_get_certificate_request(SSL *s)
 	{
 	int ok,ret=0;
 	unsigned long n,nc,l;
 	unsigned int llen,ctype_num,i;
 	X509_NAME *xn=NULL;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509_NAME) *ca_sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_REQ_A,
 		SSL3_ST_CR_CERT_REQ_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	s->s3->tmp.cert_req=0;
 
 	if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
 		goto err;
 		}
 
 	/* TLS does not like anon-DH with client cert */
 	if (s->version > SSL3_VERSION)
 		{
 		l=s->s3->tmp.new_cipher->algorithms;
 		if (l & SSL_aNULL)
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
 			goto err;
 			}
 		}
 
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* get the certificate types */
 	ctype_num= *(p++);
 	if (ctype_num > SSL3_CT_NUMBER)
 		ctype_num=SSL3_CT_NUMBER;
 	for (i=0; is3->tmp.ctype[i]= p[i];
 	p+=ctype_num;
 
 	/* get the CA RDNs */
 	n2s(p,llen);
 #if 0
 {
 FILE *out;
 out=fopen("/tmp/vsign.der","w");
 fwrite(p,1,llen,out);
 fclose(out);
 }
 #endif
 
 	if ((llen+ctype_num+2+1) != n)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
 		goto err;
 		}
 
 	for (nc=0; nc llen)
 			{
 			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 				goto cont; /* netscape bugs */
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
 			goto err;
 			}
 
 		q=p;
 
 		if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
 			{
 			/* If netscape tolerance is on, ignore errors */
 			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
 				goto cont;
 			else
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
 				goto err;
 				}
 			}
 
 		if (q != (p+l))
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
 			goto err;
 			}
 		if (!sk_X509_NAME_push(ca_sk,xn))
 			{
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		p+=l;
 		nc+=l+2;
 		}
 
 	if (0)
 		{
 cont:
 		ERR_clear_error();
 		}
 
 	/* we should setup a certificate to return.... */
 	s->s3->tmp.cert_req=1;
 	s->s3->tmp.ctype_num=ctype_num;
 	if (s->s3->tmp.ca_names != NULL)
 		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
 	s->s3->tmp.ca_names=ca_sk;
 	ca_sk=NULL;
 
 	ret=1;
 err:
 	if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
 	return(ret);
 	}
 
 static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
 	{
 	return(X509_NAME_cmp(*a,*b));
 	}
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_get_new_session_ticket(SSL *s)
 	{
 	int ok,al,ret=0, ticklen;
 	long n;
 	const unsigned char *p;
 	unsigned char *d;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SESSION_TICKET_A,
 		SSL3_ST_CR_SESSION_TICKET_B,
 		-1,
 		16384,
 		&ok);
 
 	if (!ok)
 		return((int)n);
 
 	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 	if (n < 6)
 		{
 		/* need at least ticket_lifetime_hint + ticket length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 
 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
 	if (ticklen + 6 != n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->session->tlsext_tick)
 		{
 		OPENSSL_free(s->session->tlsext_tick);
 		s->session->tlsext_ticklen = 0;
 		}
 	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
 	if (!s->session->tlsext_tick)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	memcpy(s->session->tlsext_tick, p, ticklen);
 	s->session->tlsext_ticklen = ticklen;
 	/* There are two ways to detect a resumed ticket sesion.
 	 * One is to set an appropriate session ID and then the server
 	 * must return a match in ServerHello. This allows the normal
 	 * client session ID matching to work and we know much 
 	 * earlier that the ticket has been accepted.
 	 * 
 	 * The other way is to set zero length session ID when the
 	 * ticket is presented and rely on the handshake to determine
 	 * session resumption.
 	 *
 	 * We choose the former approach because this fits in with
 	 * assumptions elsewhere in OpenSSL. The session ID is set
 	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
 	 * ticket.
 	 */ 
 	EVP_Digest(p, ticklen,
 			s->session->session_id, &s->session->session_id_length,
 #ifndef OPENSSL_NO_SHA256
 							EVP_sha256(), NULL);
 #else
 							EVP_sha1(), NULL);
 #endif
 	ret=1;
 	return(ret);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(-1);
 	}
 
 int ssl3_get_cert_status(SSL *s)
 	{
 	int ok, al;
 	unsigned long resplen;
 	long n;
 	const unsigned char *p;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_STATUS_A,
 		SSL3_ST_CR_CERT_STATUS_B,
 		SSL3_MT_CERTIFICATE_STATUS,
 		16384,
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n < 4)
 		{
 		/* need at least status type + length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	p = (unsigned char *)s->init_msg;
 	if (*p++ != TLSEXT_STATUSTYPE_ocsp)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
 		goto f_err;
 		}
 	n2l3(p, resplen);
 	if (resplen + 4 != (unsigned long)n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->tlsext_ocsp_resp)
 		OPENSSL_free(s->tlsext_ocsp_resp);
 	s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
 	if (!s->tlsext_ocsp_resp)
 		{
 		al = SSL_AD_INTERNAL_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 		goto f_err;
 		}
 	s->tlsext_ocsp_resplen = resplen;
 	if (s->ctx->tlsext_status_cb)
 		{
 		int ret;
 		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 		if (ret == 0)
 			{
 			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
 			goto f_err;
 			}
 		if (ret < 0)
 			{
 			al = SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 			goto f_err;
 			}
 		}
 	return 1;
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 	return(-1);
 	}
 #endif
 
 int ssl3_get_server_done(SSL *s)
 	{
 	int ok,ret=0;
 	long n;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_DONE_A,
 		SSL3_ST_CR_SRVR_DONE_B,
 		SSL3_MT_SERVER_DONE,
 		30, /* should be very small, like 0 :-) */
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n > 0)
 		{
 		/* should contain no data */
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
 		return -1;
 		}
 	ret=1;
 	return(ret);
 	}
 
 
 int ssl3_send_client_key_exchange(SSL *s)
 	{
 	unsigned char *p,*d;
 	int n;
 	unsigned long l;
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_KRB5
 	KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *clnt_ecdh = NULL;
 	const EC_POINT *srvr_ecpoint = NULL;
 	EVP_PKEY *srvr_pub_pkey = NULL;
 	unsigned char *encodedPoint = NULL;
 	int encoded_pt_len = 0;
 	BN_CTX * bn_ctx = NULL;
 #endif
 
 	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		l=s->s3->tmp.new_cipher->algorithms;
 
 		/* Fool emacs indentation */
 		if (0) {}
 #ifndef OPENSSL_NO_RSA
 		else if (l & SSL_kRSA)
 			{
 			RSA *rsa;
 			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 
 			if (s->session->sess_cert == NULL)
 				{
 				/* We should always have a server certificate with SSL_kRSA. */
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if (s->session->sess_cert->peer_rsa_tmp != NULL)
 				rsa=s->session->sess_cert->peer_rsa_tmp;
 			else
 				{
 				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 				if ((pkey == NULL) ||
 					(pkey->type != EVP_PKEY_RSA) ||
 					(pkey->pkey.rsa == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 				rsa=pkey->pkey.rsa;
 				EVP_PKEY_free(pkey);
 				}
 				
 			tmp_buf[0]=s->client_version>>8;
 			tmp_buf[1]=s->client_version&0xff;
 			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 					goto err;
 
 			s->session->master_key_length=sizeof tmp_buf;
 
 			q=p;
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				p+=2;
 			n=RSA_public_encrypt(sizeof tmp_buf,
 				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
 #ifdef PKCS1_CHECK
 			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
 			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
 #endif
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
 				goto err;
 				}
 
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				{
 				s2n(n,q);
 				n+=2;
 				}
 
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf,sizeof tmp_buf);
 			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
 			}
 #endif
 #ifndef OPENSSL_NO_KRB5
 		else if (l & SSL_kKRB5)
 			{
 			krb5_error_code	krb5rc;
 			KSSL_CTX	*kssl_ctx = s->kssl_ctx;
 			/*  krb5_data	krb5_ap_req;  */
 			krb5_data	*enc_ticket;
 			krb5_data	authenticator, *authp = NULL;
 			EVP_CIPHER_CTX	ciph_ctx;
 			EVP_CIPHER	*enc = NULL;
 			unsigned char	iv[EVP_MAX_IV_LENGTH];
 			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
 						+ EVP_MAX_IV_LENGTH];
 			int 		padl, outl = sizeof(epms);
 
 			EVP_CIPHER_CTX_init(&ciph_ctx);
 
 #ifdef KSSL_DEBUG
 			printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
 			        l, SSL_kKRB5);
 #endif	/* KSSL_DEBUG */
 
 			authp = NULL;
 #ifdef KRB5SENDAUTH
 			if (KRB5SENDAUTH)  authp = &authenticator;
 #endif	/* KRB5SENDAUTH */
 
 			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
 				&kssl_err);
 			enc = kssl_map_enc(kssl_ctx->enctype);
 			if (enc == NULL)
 			    goto err;
 #ifdef KSSL_DEBUG
 			{
 			printf("kssl_cget_tkt rtn %d\n", krb5rc);
 			if (krb5rc && kssl_err.text)
 			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
 			}
 #endif	/* KSSL_DEBUG */
 
 			if (krb5rc)
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,
 						SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 						kssl_err.reason);
 				goto err;
 				}
 
 			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
 			**  in place of RFC 2712 KerberosWrapper, as in:
 			**
 			**  Send ticket (copy to *p, set n = length)
 			**  n = krb5_ap_req.length;
 			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
 			**  if (krb5_ap_req.data)  
 			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
 			**
 			**  Now using real RFC 2712 KerberosWrapper
 			**  (Thanks to Simon Wilkinson )
 			**  Note: 2712 "opaque" types are here replaced
 			**  with a 2-byte length followed by the value.
 			**  Example:
 			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
 			**  Where "xx xx" = length bytes.  Shown here with
 			**  optional authenticator omitted.
 			*/
 
 			/*  KerberosWrapper.Ticket		*/
 			s2n(enc_ticket->length,p);
 			memcpy(p, enc_ticket->data, enc_ticket->length);
 			p+= enc_ticket->length;
 			n = enc_ticket->length + 2;
 
 			/*  KerberosWrapper.Authenticator	*/
 			if (authp  &&  authp->length)  
 				{
 				s2n(authp->length,p);
 				memcpy(p, authp->data, authp->length);
 				p+= authp->length;
 				n+= authp->length + 2;
 				
 				free(authp->data);
 				authp->data = NULL;
 				authp->length = 0;
 				}
 			else
 				{
 				s2n(0,p);/*  null authenticator length	*/
 				n+=2;
 				}
  
 			    tmp_buf[0]=s->client_version>>8;
 			    tmp_buf[1]=s->client_version&0xff;
 			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 				goto err;
 
 			/*  20010420 VRS.  Tried it this way; failed.
 			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
 			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
 			**				kssl_ctx->length);
 			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
 			*/
 
 			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
 			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
 				kssl_ctx->key,iv);
 			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
 				sizeof tmp_buf);
 			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
 			outl += padl;
 			if (outl > sizeof epms)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
 			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
 			s2n(outl,p);
 			memcpy(p, epms, outl);
 			p+=outl;
 			n+=outl + 2;
 
 			s->session->master_key_length=
 			        s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf, sizeof tmp_buf);
 
 			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
 			OPENSSL_cleanse(epms, outl);
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 			{
 			DH *dh_srvr,*dh_clnt;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 			        }
 
 			if (s->session->sess_cert->peer_dh_tmp != NULL)
 				dh_srvr=s->session->sess_cert->peer_dh_tmp;
 			else
 				{
 				/* we get them from the cert */
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
 				goto err;
 				}
 			
 			/* generate a new random key */
 			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 			if (!DH_generate_key(dh_clnt))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			/* use the 'p' output buffer for the DH key, but
 			 * make sure to clear it out afterwards */
 
 			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
 
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,p,n);
 			/* clean up */
 			memset(p,0,n);
 
 			/* send off the data */
 			n=BN_num_bytes(dh_clnt->pub_key);
 			s2n(n,p);
 			BN_bn2bin(dh_clnt->pub_key,p);
 			n+=2;
 
 			DH_free(dh_clnt);
 
 			/* perhaps clean things up a bit EAY EAY EAY EAY*/
 			}
 #endif
 
 #ifndef OPENSSL_NO_ECDH 
 		else if ((l & SSL_kECDH) || (l & SSL_kECDHE))
 			{
 			const EC_GROUP *srvr_group = NULL;
 			EC_KEY *tkey;
 			int ecdh_clnt_cert = 0;
 			int field_size = 0;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 				}
 
 			/* Did we send out the client's
 			 * ECDH share for use in premaster
 			 * computation as part of client certificate?
 			 * If so, set ecdh_clnt_cert to 1.
 			 */
 			if ((l & SSL_kECDH) && (s->cert != NULL)) 
 				{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates.
 				 * To add such support, one needs to add
 				 * code that checks for appropriate 
 				 * conditions and sets ecdh_clnt_cert to 1.
 				 * For example, the cert have an ECC
 				 * key on the same curve as the server's
 				 * and the key should be authorized for
 				 * key agreement.
 				 *
 				 * One also needs to add code in ssl3_connect
 				 * to skip sending the certificate verify
 				 * message.
 				 *
 				 * if ((s->cert->key->privatekey != NULL) &&
 				 *     (s->cert->key->privatekey->type ==
 				 *      EVP_PKEY_EC) && ...)
 				 * ecdh_clnt_cert = 1;
 				 */
 				}
 
 			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
 				{
 				tkey = s->session->sess_cert->peer_ecdh_tmp;
 				}
 			else
 				{
 				/* Get the Server Public Key from Cert */
 				srvr_pub_pkey = X509_get_pubkey(s->session-> \
 				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 				if ((srvr_pub_pkey == NULL) ||
 				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
 				    (srvr_pub_pkey->pkey.ec == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					    ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 
 				tkey = srvr_pub_pkey->pkey.ec;
 				}
 
 			srvr_group   = EC_KEY_get0_group(tkey);
 			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
 
 			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 				    ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 				goto err;
 				}
 			if (ecdh_clnt_cert) 
 				{ 
 				/* Reuse key info from our certificate
 				 * We only need our private key to perform
 				 * the ECDH computation.
 				 */
 				const BIGNUM *priv_key;
 				tkey = s->cert->key->privatekey->pkey.ec;
 				priv_key = EC_KEY_get0_private_key(tkey);
 				if (priv_key == NULL)
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 					goto err;
 					}
 				}
 			else 
 				{
 				/* Generate a new ECDH key pair */
 				if (!(EC_KEY_generate_key(clnt_ecdh)))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
 					goto err;
 					}
 				}
 
 			/* use the 'p' output buffer for the ECDH key, but
 			 * make sure to clear it out afterwards
 			 */
 
 			field_size = EC_GROUP_get_degree(srvr_group);
 			if (field_size <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length = s->method->ssl3_enc \
 			    -> generate_master_secret(s, 
 				s->session->master_key,
 				p, n);
 
 			memset(p, 0, n); /* clean up */
 
 			if (ecdh_clnt_cert) 
 				{
 				/* Send empty client key exch message */
 				n = 0;
 				}
 			else 
 				{
 				/* First check the size of encoding and
 				 * allocate memory accordingly.
 				 */
 				encoded_pt_len = 
 				    EC_POINT_point2oct(srvr_group, 
 					EC_KEY_get0_public_key(clnt_ecdh), 
 					POINT_CONVERSION_UNCOMPRESSED, 
 					NULL, 0, NULL);
 
 				encodedPoint = (unsigned char *) 
 				    OPENSSL_malloc(encoded_pt_len * 
 					sizeof(unsigned char)); 
 				bn_ctx = BN_CTX_new();
 				if ((encodedPoint == NULL) || 
 				    (bn_ctx == NULL)) 
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 
 				/* Encode the public key */
 				n = EC_POINT_point2oct(srvr_group, 
 				    EC_KEY_get0_public_key(clnt_ecdh), 
 				    POINT_CONVERSION_UNCOMPRESSED, 
 				    encodedPoint, encoded_pt_len, bn_ctx);
 
 				*p = n; /* length of encoded point */
 				/* Encoded point will be copied here */
 				p += 1; 
 				/* copy the point */
 				memcpy((unsigned char *)p, encodedPoint, n);
 				/* increment n to account for length field */
 				n += 1; 
 				}
 
 			/* Free allocated memory */
 			BN_CTX_free(bn_ctx);
 			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 			if (clnt_ecdh != NULL) 
 				 EC_KEY_free(clnt_ecdh);
 			EVP_PKEY_free(srvr_pub_pkey);
 			}
 #endif /* !OPENSSL_NO_ECDH */
 		else
 			{
 			ssl3_send_alert(s, SSL3_AL_FATAL,
 			    SSL_AD_HANDSHAKE_FAILURE);
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 			    ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		
 		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_KEY_EXCH_B;
 		/* number of bytes to write */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_KEY_EXCH_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	if (clnt_ecdh != NULL) 
 		EC_KEY_free(clnt_ecdh);
 	EVP_PKEY_free(srvr_pub_pkey);
 #endif
 	return(-1);
 	}
 
 int ssl3_send_client_verify(SSL *s)
 	{
 	unsigned char *p,*d;
 	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	EVP_PKEY *pkey;
 #ifndef OPENSSL_NO_RSA
 	unsigned u=0;
 #endif
 	unsigned long n;
 #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
 	int j;
 #endif
 
 	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 		pkey=s->cert->key->privatekey;
 
 		s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
 			&(data[MD5_DIGEST_LENGTH]));
 
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA)
 			{
 			s->method->ssl3_enc->cert_verify_mac(s,
 				&(s->s3->finish_dgst1),&(data[0]));
 			if (RSA_sign(NID_md5_sha1, data,
 					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
 				goto err;
 				}
 			s2n(u,p);
 			n=u+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DSA
 			if (pkey->type == EVP_PKEY_DSA)
 			{
 			if (!DSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.dsa))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			if (pkey->type == EVP_PKEY_EC)
 			{
 			if (!ECDSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.ec))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 				    ERR_R_ECDSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_CERT_VRFY_B;
 		s->init_num=(int)n+4;
 		s->init_off=0;
 		}
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_send_client_certificate(SSL *s)
 	{
 	X509 *x509=NULL;
 	EVP_PKEY *pkey=NULL;
 	int i;
 	unsigned long l;
 
 	if (s->state ==	SSL3_ST_CW_CERT_A)
 		{
 		if ((s->cert == NULL) ||
 			(s->cert->key->x509 == NULL) ||
 			(s->cert->key->privatekey == NULL))
 			s->state=SSL3_ST_CW_CERT_B;
 		else
 			s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	/* We need to get a client cert */
 	if (s->state == SSL3_ST_CW_CERT_B)
 		{
 		/* If we get an error, we need to
 		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
 		 * We then get retied later */
 		i=0;
 		i = ssl_do_client_cert_cb(s, &x509, &pkey);
 		if (i < 0)
 			{
 			s->rwstate=SSL_X509_LOOKUP;
 			return(-1);
 			}
 		s->rwstate=SSL_NOTHING;
 		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
 			{
 			s->state=SSL3_ST_CW_CERT_B;
 			if (	!SSL_use_certificate(s,x509) ||
 				!SSL_use_PrivateKey(s,pkey))
 				i=0;
 			}
 		else if (i == 1)
 			{
 			i=0;
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
 			}
 
 		if (x509 != NULL) X509_free(x509);
 		if (pkey != NULL) EVP_PKEY_free(pkey);
 		if (i == 0)
 			{
 			if (s->version == SSL3_VERSION)
 				{
 				s->s3->tmp.cert_req=0;
 				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
 				return(1);
 				}
 			else
 				{
 				s->s3->tmp.cert_req=2;
 				}
 			}
 
 		/* Ok, we have a cert */
 		s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	if (s->state == SSL3_ST_CW_CERT_C)
 		{
 		s->state=SSL3_ST_CW_CERT_D;
 		l=ssl3_output_cert_chain(s,
 			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 	/* SSL3_ST_CW_CERT_D */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 #define has_bits(i,m)	(((i)&(m)) == (m))
 
 int ssl3_check_cert_and_algorithm(SSL *s)
 	{
 	int i,idx;
 	long algs;
 	EVP_PKEY *pkey=NULL;
 	SESS_CERT *sc;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh;
 #endif
 
 	sc=s->session->sess_cert;
 
 	algs=s->s3->tmp.new_cipher->algorithms;
 
 	/* we don't have a certificate */
 	if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
 		return(1);
 
 	if (sc == NULL)
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 #ifndef OPENSSL_NO_RSA
 	rsa=s->session->sess_cert->peer_rsa_tmp;
 #endif
 #ifndef OPENSSL_NO_DH
 	dh=s->session->sess_cert->peer_dh_tmp;
 #endif
 
 	/* This is the passed certificate */
 
 	idx=sc->peer_cert_type;
 #ifndef OPENSSL_NO_ECDH
 	if (idx == SSL_PKEY_ECC)
 		{
 		if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
 		    s->s3->tmp.new_cipher) == 0) 
 			{ /* check failed */
 			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
 			goto f_err;			
 			}
 		else 
 			{
 			return 1;
 			}
 		}
 #endif
 	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
 	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
 	EVP_PKEY_free(pkey);
 
 	
 	/* Check that we have a certificate if we require one */
 	if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_DSA
 	else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
 		goto f_err;
 		}
 #endif
 #ifndef OPENSSL_NO_RSA
 	if ((algs & SSL_kRSA) &&
 		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
 		goto f_err;
 		}
 #endif
 #ifndef OPENSSL_NO_DH
 	if ((algs & SSL_kEDH) &&
 		!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
 		goto f_err;
 		}
 	else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_DSA
 	else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
 		goto f_err;
 		}
 #endif
 #endif
 
 	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
 		{
 #ifndef OPENSSL_NO_RSA
 		if (algs & SSL_kRSA)
 			{
 			if (rsa == NULL
 			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
 				{
 				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DH
 			if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 			    {
 			    if (dh == NULL
 				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
 				{
 				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
 				goto f_err;
 				}
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		}
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 err:
 	return(0);
 	}
 
 
 #ifndef OPENSSL_NO_ECDH
 /* This is the complement of nid2curve_id in s3_srvr.c. */
 static int curve_id2nid(int curve_id)
 {
 	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
 	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
 	static int nid_list[26] =
 	{
 		0,
 		NID_sect163k1, /* sect163k1 (1) */
 		NID_sect163r1, /* sect163r1 (2) */
 		NID_sect163r2, /* sect163r2 (3) */
 		NID_sect193r1, /* sect193r1 (4) */ 
 		NID_sect193r2, /* sect193r2 (5) */ 
 		NID_sect233k1, /* sect233k1 (6) */
 		NID_sect233r1, /* sect233r1 (7) */ 
 		NID_sect239k1, /* sect239k1 (8) */ 
 		NID_sect283k1, /* sect283k1 (9) */
 		NID_sect283r1, /* sect283r1 (10) */ 
 		NID_sect409k1, /* sect409k1 (11) */ 
 		NID_sect409r1, /* sect409r1 (12) */
 		NID_sect571k1, /* sect571k1 (13) */ 
 		NID_sect571r1, /* sect571r1 (14) */ 
 		NID_secp160k1, /* secp160k1 (15) */
 		NID_secp160r1, /* secp160r1 (16) */ 
 		NID_secp160r2, /* secp160r2 (17) */ 
 		NID_secp192k1, /* secp192k1 (18) */
 		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
 		NID_secp224k1, /* secp224k1 (20) */ 
 		NID_secp224r1, /* secp224r1 (21) */
 		NID_secp256k1, /* secp256k1 (22) */ 
 		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
 		NID_secp384r1, /* secp384r1 (24) */
 		NID_secp521r1  /* secp521r1 (25) */	
 	};
 	
 	if ((curve_id < 1) || (curve_id > 25)) return 0;
 
 	return nid_list[curve_id];
 }
 #endif
 
 /* Check to see if handshake is full or resumed. Usually this is just a
  * case of checking to see if a cache hit has occurred. In the case of
  * session tickets we have to check the next message to be sure.
  */
 
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_check_finished(SSL *s)
 	{
 	int ok;
 	long n;
 	/* If we have no ticket or session ID is non-zero length (a match of
 	 * a non-zero session length would never reach here) it cannot be a
 	 * resumed session.
 	 */
 	if (!s->session->tlsext_tick || s->session->session_id_length)
 		return 1;
 	/* this function is called when we really expect a Certificate
 	 * message, so permit appropriate message length */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_A,
 		SSL3_ST_CR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 	s->s3->tmp.reuse_message = 1;
 	if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
 		|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
 		return 2;
 
 	return 1;
 	}
 #endif
 
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 	{
 	int i = 0;
 #ifndef OPENSSL_NO_ENGINE
 	if (s->ctx->client_cert_engine)
 		{
 		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
 						SSL_get_client_CA_list(s),
 						px509, ppkey, NULL, NULL, NULL);
 		if (i != 0)
 			return i;
 		}
 #endif
 	if (s->ctx->client_cert_cb)
 		i = s->ctx->client_cert_cb(s,px509,ppkey);
 	return i;
 	}
Index: releng/8.4/crypto/openssl/ssl/s3_srvr.c
===================================================================
--- releng/8.4/crypto/openssl/ssl/s3_srvr.c	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/s3_srvr.c	(revision 284295)
@@ -1,2914 +1,2924 @@
 /* ssl/s3_srvr.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 
 #define REUSE_CIPHER_BUG
 #define NETSCAPE_HANG_BUG
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include "../crypto/constant_time_locl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_KRB5
 #include 
 #endif
 #include 
 
 static SSL_METHOD *ssl3_get_server_method(int ver);
 #ifndef OPENSSL_NO_ECDH
 static int nid2curve_id(int nid);
 #endif
 
 static SSL_METHOD *ssl3_get_server_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_server_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
 			ssl3_accept,
 			ssl_undefined_function,
 			ssl3_get_server_method)
 
 int ssl3_accept(SSL *s)
 	{
 	BUF_MEM *buf;
 	unsigned long l,Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 
 	/* init things to blank */
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
 
 	if (s->cert == NULL)
 		{
 		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
 		return(-1);
 		}
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch (s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->new_session=1;
 			/* s->state=SSL_ST_ACCEPT; */
 
 		case SSL_ST_BEFORE:
 		case SSL_ST_ACCEPT:
 		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
 		case SSL_ST_OK|SSL_ST_ACCEPT:
 
 			s->server=1;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version>>8) != 3)
 				{
 				SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
 				return -1;
 				}
 			s->type=SSL_ST_ACCEPT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				}
 
 			if (!ssl3_setup_buffers(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			s->init_num=0;
 			s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
 
 			if (s->state != SSL_ST_RENEGOTIATE)
 				{
 				/* Ok, we now need to push on a buffering BIO so that
 				 * the output is sent in a way that TCP likes :-)
 				 */
 				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
 				
 				ssl3_init_finished_mac(s);
 				s->state=SSL3_ST_SR_CLNT_HELLO_A;
 				s->ctx->stats.sess_accept++;
 				}
 			else if (!s->s3->send_connection_binding &&
 				!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
 				{
 				/* Server attempting to renegotiate with
 				 * client that doesn't support secure
 				 * renegotiation.
 				 */
 				SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				ret = -1;
 				goto end;
 				}
 			else
 				{
 				/* s->state == SSL_ST_RENEGOTIATE,
 				 * we will just send a HelloRequest */
 				s->ctx->stats.sess_accept_renegotiate++;
 				s->state=SSL3_ST_SW_HELLO_REQ_A;
 				}
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_A:
 		case SSL3_ST_SW_HELLO_REQ_B:
 
 			s->shutdown=0;
 			ret=ssl3_send_hello_request(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 
 			ssl3_init_finished_mac(s);
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_C:
 			s->state=SSL_ST_OK;
 			break;
 
 		case SSL3_ST_SR_CLNT_HELLO_A:
 		case SSL3_ST_SR_CLNT_HELLO_B:
 		case SSL3_ST_SR_CLNT_HELLO_C:
 
 			s->shutdown=0;
 			ret=ssl3_get_client_hello(s);
 			if (ret <= 0) goto end;
 			s->new_session = 2;
 			s->state=SSL3_ST_SW_SRVR_HELLO_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_SRVR_HELLO_A:
 		case SSL3_ST_SW_SRVR_HELLO_B:
 			ret=ssl3_send_server_hello(s);
 			if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 			if (s->hit)
 				{
 				if (s->tlsext_ticket_expected)
 					s->state=SSL3_ST_SW_SESSION_TICKET_A;
 				else
 					s->state=SSL3_ST_SW_CHANGE_A;
 				}
 #else
 			if (s->hit)
 					s->state=SSL3_ST_SW_CHANGE_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_A:
 		case SSL3_ST_SW_CERT_B:
 			/* Check if it is anon DH or anon ECDH or KRB5 */
 			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
 				&& !(s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
 				{
 				ret=ssl3_send_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_SW_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_KEY_EXCH_A:
 		case SSL3_ST_SW_KEY_EXCH_B:
 			l=s->s3->tmp.new_cipher->algorithms;
 
 			/* clear this, it may get reset by
 			 * send_server_key_exchange */
 			s->s3->tmp.use_rsa_tmp=0;
 
 
 			/* only send if a DH key exchange, fortezza or
 			 * RSA but we have a sign only certificate
 			 *
 			 * For ECC ciphersuites, we send a serverKeyExchange
 			 * message only if the cipher suite is either
 			 * ECDH-anon or ECDHE. In other cases, the
 			 * server certificate contains the server's 
 			 * public key for key exchange.
 			 */
 			if ((l & SSL_kECDHE)
 			    || (l & (SSL_DH|SSL_kFZA))
 			    || ((l & SSL_kRSA)
 				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
 				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
 					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
 					)
 				    )
 				)
 			    )
 				{
 				ret=ssl3_send_server_key_exchange(s);
 				if (ret <= 0) goto end;
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_CERT_REQ_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_REQ_A:
 		case SSL3_ST_SW_CERT_REQ_B:
 			if (/* don't request cert unless asked for it: */
 				!(s->verify_mode & SSL_VERIFY_PEER) ||
 				/* if SSL_VERIFY_CLIENT_ONCE is set,
 				 * don't request cert during re-negotiation: */
 				((s->session->peer != NULL) &&
 				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
 				/* never request cert in anonymous ciphersuites
 				 * (see section "Certificate request" in SSL 3 drafts
 				 * and in RFC 2246): */
 				((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&
 				 /* ... except when the application insists on verification
 				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
 				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
                                  /* never request cert in Kerberos ciphersuites */
                                 (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
 				{
 				/* no cert request */
 				skip=1;
 				s->s3->tmp.cert_request=0;
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 				}
 			else
 				{
 				s->s3->tmp.cert_request=1;
 				ret=ssl3_send_certificate_request(s);
 				if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 #else
 				s->state=SSL3_ST_SW_FLUSH;
 				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 #endif
 				s->init_num=0;
 				}
 			break;
 
 		case SSL3_ST_SW_SRVR_DONE_A:
 		case SSL3_ST_SW_SRVR_DONE_B:
 			ret=ssl3_send_server_done(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 			break;
 		
 		case SSL3_ST_SW_FLUSH:
 
 			/* This code originally checked to see if
 			 * any data was pending using BIO_CTRL_INFO
 			 * and then flushed. This caused problems
 			 * as documented in PR#1939. The proposed
 			 * fix doesn't completely resolve this issue
 			 * as buggy implementations of BIO_CTRL_PENDING
 			 * still exist. So instead we just flush
 			 * unconditionally.
 			 */
 
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL3_ST_SR_CERT_A:
 		case SSL3_ST_SR_CERT_B:
 			/* Check for second client hello (MS SGC) */
 			ret = ssl3_check_client_hello(s);
 			if (ret <= 0)
 				goto end;
 			if (ret == 2)
 				s->state = SSL3_ST_SR_CLNT_HELLO_C;
 			else {
 				if (s->s3->tmp.cert_request)
 					{
 					ret=ssl3_get_client_certificate(s);
 					if (ret <= 0) goto end;
 					}
 				s->init_num=0;
 				s->state=SSL3_ST_SR_KEY_EXCH_A;
 			}
 			break;
 
 		case SSL3_ST_SR_KEY_EXCH_A:
 		case SSL3_ST_SR_KEY_EXCH_B:
 			ret=ssl3_get_client_key_exchange(s);
 			if (ret <= 0) 
 				goto end;
 			if (ret == 2)
 				{
 				/* For the ECDH ciphersuites when
 				 * the client sends its ECDH pub key in
 				 * a certificate, the CertificateVerify
 				 * message is not sent.
 				 */
 				s->state=SSL3_ST_SR_FINISHED_A;
 				s->init_num = 0;
 				}
 			else   
 				{
 				s->state=SSL3_ST_SR_CERT_VRFY_A;
 				s->init_num=0;
 
 				/* We need to get hashes here so if there is
 				 * a client cert, it can be verified
 				 */ 
 				s->method->ssl3_enc->cert_verify_mac(s,
 				    &(s->s3->finish_dgst1),
 				    &(s->s3->tmp.cert_verify_md[0]));
 				s->method->ssl3_enc->cert_verify_mac(s,
 				    &(s->s3->finish_dgst2),
 				    &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
 				}
 			break;
 
 		case SSL3_ST_SR_CERT_VRFY_A:
 		case SSL3_ST_SR_CERT_VRFY_B:
 
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			/* we should decide if we expected this one */
 			ret=ssl3_get_cert_verify(s);
 			if (ret <= 0) goto end;
 
 			s->state=SSL3_ST_SR_FINISHED_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SR_FINISHED_A:
 		case SSL3_ST_SR_FINISHED_B:
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
 				SSL3_ST_SR_FINISHED_B);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				s->state=SSL_ST_OK;
 #ifndef OPENSSL_NO_TLSEXT
 			else if (s->tlsext_ticket_expected)
 				s->state=SSL3_ST_SW_SESSION_TICKET_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_SW_SESSION_TICKET_A:
 		case SSL3_ST_SW_SESSION_TICKET_B:
 			ret=ssl3_send_newsession_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_STATUS_A:
 		case SSL3_ST_SW_CERT_STATUS_B:
 			ret=ssl3_send_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 #endif
 
 		case SSL3_ST_SW_CHANGE_A:
 		case SSL3_ST_SW_CHANGE_B:
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{ ret= -1; goto end; }
 
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
 
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FINISHED_A;
 			s->init_num=0;
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_SERVER_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 		case SSL3_ST_SW_FINISHED_A:
 		case SSL3_ST_SW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
 				s->method->ssl3_enc->server_finished_label,
 				s->method->ssl3_enc->server_finished_label_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
 				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
 			else
 				s->s3->tmp.next_state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			BUF_MEM_free(s->init_buf);
 			s->init_buf=NULL;
 
 			/* remove buffering on output */
 			ssl_free_wbio_buffer(s);
 
 			s->init_num=0;
 
 			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
 				{
 				/* actually not necessarily a 'new' session unless
 				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 				
 				s->new_session=0;
 				
 				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
 				
 				s->ctx->stats.sess_accept_good++;
 				/* s->server=1; */
 				s->handshake_func=ssl3_accept;
 
 				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 				}
 			
 			ret = 1;
 			goto end;
 			/* break; */
 
 		default:
 			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 		
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_ACCEPT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	/* BIO_flush(s->wbio); */
 
 	s->in_handshake--;
 	if (cb != NULL)
 		cb(s,SSL_CB_ACCEPT_EXIT,ret);
 	return(ret);
 	}
 
 int ssl3_send_hello_request(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 		*(p++)=SSL3_MT_HELLO_REQUEST;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_HELLO_REQ_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_HELLO_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_check_client_hello(SSL *s)
 	{
 	int ok;
 	long n;
 
 	/* this function is called when we really expect a Certificate message,
 	 * so permit appropriate message length */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 	s->s3->tmp.reuse_message = 1;
 	if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
 		{
 		/* We only allow the client to restart the handshake once per
 		 * negotiation. */
 		if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
 			{
 			SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
 			return -1;
 			}
 		/* Throw away what we have done so far in the current handshake,
 		 * which will now be aborted. (A full SSL_clear would be too much.) */
 #ifndef OPENSSL_NO_DH
 		if (s->s3->tmp.dh != NULL)
 			{
 			DH_free(s->s3->tmp.dh);
 			s->s3->tmp.dh = NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->s3->tmp.ecdh != NULL)
 			{
 			EC_KEY_free(s->s3->tmp.ecdh);
 			s->s3->tmp.ecdh = NULL;
 			}
 #endif
 		s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
 		return 2;
 		}
 	return 1;
 }
 
 int ssl3_get_client_hello(SSL *s)
 	{
 	int i,j,ok,al,ret= -1;
 	unsigned int cookie_len;
 	long n;
 	unsigned long id;
 	unsigned char *p,*d,*q;
 	SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp=NULL;
 #endif
 	STACK_OF(SSL_CIPHER) *ciphers=NULL;
 
 	/* We do this so that we will respond with our native type.
 	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
 	 * This down switching should be handled by a different method.
 	 * If we are SSLv3, we will respond with SSLv3, even if prompted with
 	 * TLSv1.
 	 */
 	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
 		{
 		s->state=SSL3_ST_SR_CLNT_HELLO_B;
 		}
 	s->first_packet=1;
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CLNT_HELLO_B,
 		SSL3_ST_SR_CLNT_HELLO_C,
 		SSL3_MT_CLIENT_HELLO,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 	s->first_packet=0;
 	d=p=(unsigned char *)s->init_msg;
 
 	/* use version from inside client hello, not from record header
 	 * (may differ: see RFC 2246, Appendix E, second paragraph) */
 	s->client_version=(((int)p[0])<<8)|(int)p[1];
 	p+=2;
 
 	if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
 	    (s->version != DTLS1_VERSION && s->client_version < s->version))
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
 		if ((s->client_version>>8) == SSL3_VERSION_MAJOR) 
 			{
 			/* similar to ssl3_get_record, send alert using remote version number */
 			s->version = s->client_version;
 			}
 		al = SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 
 	/* If we require cookies and this ClientHello doesn't
 	 * contain one, just return since we do not want to
 	 * allocate any memory yet. So check cookie length...
 	 */
 	if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
 		{
 		unsigned int session_length, cookie_length;
 		
 		session_length = *(p + SSL3_RANDOM_SIZE);
 		cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
 
 		if (cookie_length == 0)
 			return 1;
 		}
 
 	/* load the client random */
 	memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	/* get the session-id */
 	j= *(p++);
 
 	s->hit=0;
 	/* Versions before 0.9.7 always allow session reuse during renegotiation
 	 * (i.e. when s->new_session is true), option
 	 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
 	 * Maybe this optional behaviour should always have been the default,
 	 * but we cannot safely change the default behaviour (or new applications
 	 * might be written that become totally unsecure when compiled with
 	 * an earlier library version)
 	 */
 	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
 		{
 		if (!ssl_get_new_session(s,1))
 			goto err;
 		}
 	else
 		{
 		i=ssl_get_prev_session(s, p, j, d + n);
 		if (i == 1)
 			{ /* previous session */
 			s->hit=1;
 			}
 		else if (i == -1)
 			goto err;
 		else /* i == 0 */
 			{
 			if (!ssl_get_new_session(s,1))
 				goto err;
 			}
 		}
 
 	p+=j;
 
 	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
 		{
 		/* cookie stuff */
 		cookie_len = *(p++);
 
 		/* 
 		 * The ClientHello may contain a cookie even if the
 		 * HelloVerify message has not been sent--make sure that it
 		 * does not cause an overflow.
 		 */
 		if ( cookie_len > sizeof(s->d1->rcvd_cookie))
 			{
 			/* too much data */
 			al = SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
 			goto f_err;
 			}
 
 		/* verify the cookie if appropriate option is set. */
 		if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
 			cookie_len > 0)
 			{
 			memcpy(s->d1->rcvd_cookie, p, cookie_len);
 
 			if ( s->ctx->app_verify_cookie_cb != NULL)
 				{
 				if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
 					cookie_len) == 0)
 					{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 					}
 				/* else cookie verification succeeded */
 				}
 			else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, 
 						  s->d1->cookie_len) != 0) /* default verification */
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 				}
 
 			ret = 2;
 			}
 
 		p += cookie_len;
 		}
 
 	n2s(p,i);
 	if ((i == 0) && (j != 0))
 		{
 		/* we need a cipher if we are not resuming a session */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);
 		goto f_err;
 		}
 	if ((p+i) >= (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))
 		== NULL))
 		{
 		goto err;
 		}
 	p+=i;
 
 	/* If it is a hit, check that the cipher is in the list */
 	if ((s->hit) && (i > 0))
 		{
 		j=0;
 		id=s->session->cipher->id;
 
 #ifdef CIPHER_DEBUG
 		printf("client sent %d ciphers\n",sk_num(ciphers));
 #endif
 		for (i=0; iid == id)
 				{
 				j=1;
 				break;
 				}
 			}
 /* Disabled because it can be used in a ciphersuite downgrade
  * attack: CVE-2010-4180.
  */
 #if 0
 		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
 			{
 			/* Special case as client bug workaround: the previously used cipher may
 			 * not be in the current list, the client instead might be trying to
 			 * continue using a cipher that before wasn't chosen due to server
 			 * preferences.  We'll have to reject the connection if the cipher is not
 			 * enabled, though. */
 			c = sk_SSL_CIPHER_value(ciphers, 0);
 			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
 				{
 				s->session->cipher = c;
 				j = 1;
 				}
 			}
 #endif
 		if (j == 0)
 			{
 			/* we need to have the cipher in the cipher
 			 * list if we are asked to reuse it */
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
 			goto f_err;
 			}
 		}
 
 	/* compression */
 	i= *(p++);
 	if ((p+i) > (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	q=p;
 	for (j=0; j= i)
 		{
 		/* no compress */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_clienthello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err;
 			}
 		}
 		if (ssl_check_clienthello_tlsext_early(s) <= 0) {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 		}
 #endif
 	/* Worst case, we will use the NULL compression, but if we have other
 	 * options, we will now look for them.  We have i-1 compression
 	 * algorithms from the client, starting at q. */
 	s->s3->tmp.new_compression=NULL;
 #ifndef OPENSSL_NO_COMP
 	if (s->ctx->comp_methods != NULL)
 		{ /* See if we have a match */
 		int m,nn,o,v,done=0;
 
 		nn=sk_SSL_COMP_num(s->ctx->comp_methods);
 		for (m=0; mctx->comp_methods,m);
 			v=comp->id;
 			for (o=0; os3->tmp.new_compression=comp;
 		else
 			comp=NULL;
 		}
 #endif
 
 	/* TLS does not mind if there is extra stuff */
 #if 0   /* SSL 3.0 does not mind either, so we should disable this test
          * (was enabled in 0.9.6d through 0.9.6j and 0.9.7 through 0.9.7b,
          * in earlier SSLeay/OpenSSL releases this test existed but was buggy) */
 	if (s->version == SSL3_VERSION)
 		{
 		if (p < (d+n))
 			{
 			/* wrong number of bytes,
 			 * there could be more to follow */
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		}
 #endif
 
 	/* Given s->session->ciphers and SSL_get_ciphers, we must
 	 * pick a cipher */
 
 	if (!s->hit)
 		{
 #ifdef OPENSSL_NO_COMP
 		s->session->compress_meth=0;
 #else
 		s->session->compress_meth=(comp == NULL)?0:comp->id;
 #endif
 		if (s->session->ciphers != NULL)
 			sk_SSL_CIPHER_free(s->session->ciphers);
 		s->session->ciphers=ciphers;
 		if (ciphers == NULL)
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);
 			goto f_err;
 			}
 		ciphers=NULL;
 		c=ssl3_choose_cipher(s,s->session->ciphers,
 				     SSL_get_ciphers(s));
 
 		if (c == NULL)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
 			goto f_err;
 			}
 		s->s3->tmp.new_cipher=c;
 		}
 	else
 		{
 		/* Session-id reuse */
 #ifdef REUSE_CIPHER_BUG
 		STACK_OF(SSL_CIPHER) *sk;
 		SSL_CIPHER *nc=NULL;
 		SSL_CIPHER *ec=NULL;
 
 		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
 			{
 			sk=s->session->ciphers;
 			for (i=0; ialgorithms & SSL_eNULL)
 					nc=c;
 				if (SSL_C_IS_EXPORT(c))
 					ec=c;
 				}
 			if (nc != NULL)
 				s->s3->tmp.new_cipher=nc;
 			else if (ec != NULL)
 				s->s3->tmp.new_cipher=ec;
 			else
 				s->s3->tmp.new_cipher=s->session->cipher;
 			}
 		else
 #endif
 		s->s3->tmp.new_cipher=s->session->cipher;
 		}
 	
 	/* we now have the following setup. 
 	 * client_random
 	 * cipher_list 		- our prefered list of ciphers
 	 * ciphers 		- the clients prefered list of ciphers
 	 * compression		- basically ignored right now
 	 * ssl version is set	- sslv3
 	 * s->session		- The ssl session has been setup.
 	 * s->hit		- session reuse flag
 	 * s->tmp.new_cipher	- the new cipher to use.
 	 */
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* Handles TLS extensions that we couldn't check earlier */
 	if (s->version >= SSL3_VERSION)
 		{
 		if (ssl_check_clienthello_tlsext_late(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 			}
 		}
 #endif
 
 	if (ret < 0) ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
 	return(ret);
 	}
 
 int ssl3_send_server_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i,sl;
 	unsigned long l,Time;
 
 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
 		{
 		buf=(unsigned char *)s->init_buf->data;
 		p=s->s3->server_random;
 		Time=(unsigned long)time(NULL);			/* Time */
 		l2n(Time,p);
 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
 			return -1;
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 
 		/* Random stuff */
 		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* now in theory we have 3 options to sending back the
 		 * session id.  If it is a re-use, we send back the
 		 * old session-id, if it is a new session, we send
 		 * back the new session-id or we send back a 0 length
 		 * session-id if we want it to be single use.
 		 * Currently I will not implement the '0' length session-id
 		 * 12-Jan-98 - I'll now support the '0' length stuff.
 		 *
 		 * We also have an additional case where stateless session
 		 * resumption is successful: we always send back the old
 		 * session id. In this case s->hit is non zero: this can
 		 * only happen if stateless session resumption is succesful
 		 * if session caching is disabled so existing functionality
 		 * is unaffected.
 		 */
 		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
 			&& !s->hit)
 			s->session->session_id_length=0;
 
 		sl=s->session->session_id_length;
 		if (sl > (int)sizeof(s->session->session_id))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 		*(p++)=sl;
 		memcpy(p,s->session->session_id,sl);
 		p+=sl;
 
 		/* put the cipher */
 		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
 		p+=i;
 
 		/* put the compression method */
 #ifdef OPENSSL_NO_COMP
 			*(p++)=0;
 #else
 		if (s->s3->tmp.new_compression == NULL)
 			*(p++)=0;
 		else
 			*(p++)=s->s3->tmp.new_compression->id;
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 #endif
 		/* do the header */
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_SERVER_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_SW_SRVR_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_done(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_SRVR_DONE_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_SRVR_DONE_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	int j,num;
 	RSA *rsa;
 	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	unsigned int u;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL,*dhp;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh=NULL, *ecdhp;
 	unsigned char *encodedPoint = NULL;
 	int encodedlen = 0;
 	int curve_id = 0;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 	EVP_PKEY *pkey;
 	unsigned char *p,*d;
 	int al,i;
 	unsigned long type;
 	int n;
 	CERT *cert;
 	BIGNUM *r[4];
 	int nr[4],kn;
 	BUF_MEM *buf;
 	EVP_MD_CTX md_ctx;
 
 	EVP_MD_CTX_init(&md_ctx);
 	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
 		{
 		type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;
 		cert=s->cert;
 
 		buf=s->init_buf;
 
 		r[0]=r[1]=r[2]=r[3]=NULL;
 		n=0;
 #ifndef OPENSSL_NO_RSA
 		if (type & SSL_kRSA)
 			{
 			rsa=cert->rsa_tmp;
 			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
 				{
 				rsa=s->cert->rsa_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				if(rsa == NULL)
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
 					goto f_err;
 				}
 				RSA_up_ref(rsa);
 				cert->rsa_tmp=rsa;
 				}
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
 				goto f_err;
 				}
 			r[0]=rsa->n;
 			r[1]=rsa->e;
 			s->s3->tmp.use_rsa_tmp=1;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DH
 			if (type & SSL_kEDH)
 			{
 			dhp=cert->dh_tmp;
 			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
 				dhp=s->cert->dh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 			if (dhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.dh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((dh=DHparams_dup(dhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.dh=dh;
 			if ((dhp->pub_key == NULL ||
 			     dhp->priv_key == NULL ||
 			     (s->options & SSL_OP_SINGLE_DH_USE)))
 				{
 				if(!DH_generate_key(dh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
 					   ERR_R_DH_LIB);
 				    goto err;
 				    }
 				}
 			else
 				{
 				dh->pub_key=BN_dup(dhp->pub_key);
 				dh->priv_key=BN_dup(dhp->priv_key);
 				if ((dh->pub_key == NULL) ||
 					(dh->priv_key == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 					goto err;
 					}
 				}
 			r[0]=dh->p;
 			r[1]=dh->g;
 			r[2]=dh->pub_key;
 			}
 		else 
 #endif
 #ifndef OPENSSL_NO_ECDH
 			if (type & SSL_kECDHE)
 			{
 			const EC_GROUP *group;
 
 			ecdhp=cert->ecdh_tmp;
 			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
 				{
 				ecdhp=s->cert->ecdh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				}
 			if (ecdhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.ecdh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			/* Duplicate the ECDH structure. */
 			if (ecdhp == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.ecdh=ecdh;
 			if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL) ||
 			    (s->options & SSL_OP_SINGLE_ECDH_USE))
 				{
 				if(!EC_KEY_generate_key(ecdh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				    goto err;
 				    }
 				}
 
 			if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
 			    (EC_KEY_get0_public_key(ecdh)  == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 			    (EC_GROUP_get_degree(group) > 163)) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 				goto err;
 				}
 
 			/* XXX: For now, we only support ephemeral ECDH
 			 * keys over named (not generic) curves. For 
 			 * supported named curves, curve_id is non-zero.
 			 */
 			if ((curve_id = 
 			    nid2curve_id(EC_GROUP_get_curve_name(group)))
 			    == 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
 				goto err;
 				}
 
 			/* Encode the public key.
 			 * First check the size of encoding and
 			 * allocate memory accordingly.
 			 */
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh),
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    NULL, 0, NULL);
 
 			encodedPoint = (unsigned char *) 
 			    OPENSSL_malloc(encodedlen*sizeof(unsigned char)); 
 			bn_ctx = BN_CTX_new();
 			if ((encodedPoint == NULL) || (bn_ctx == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh), 
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    encodedPoint, encodedlen, bn_ctx);
 
 			if (encodedlen == 0) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			BN_CTX_free(bn_ctx);  bn_ctx=NULL;
 
 			/* XXX: For now, we only support named (not 
 			 * generic) curves in ECDH ephemeral key exchanges.
 			 * In this situation, we need four additional bytes
 			 * to encode the entire ServerECDHParams
 			 * structure. 
 			 */
 			n = 4 + encodedlen;
 
 			/* We'll generate the serverKeyExchange message
 			 * explicitly so we can set these to NULLs
 			 */
 			r[0]=NULL;
 			r[1]=NULL;
 			r[2]=NULL;
 			r[3]=NULL;
 			}
 		else 
 #endif /* !OPENSSL_NO_ECDH */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		for (i=0; r[i] != NULL; i++)
 			{
 			nr[i]=BN_num_bytes(r[i]);
 			n+=2+nr[i];
 			}
 
 		if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
 			{
 			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
 				== NULL)
 				{
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			kn=EVP_PKEY_size(pkey);
 			}
 		else
 			{
 			pkey=NULL;
 			kn=0;
 			}
 
 		if (!BUF_MEM_grow_clean(buf,n+4+kn))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
 			goto err;
 			}
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		for (i=0; r[i] != NULL; i++)
 			{
 			s2n(nr[i],p);
 			BN_bn2bin(r[i],p);
 			p+=nr[i];
 			}
 
 #ifndef OPENSSL_NO_ECDH
 		if (type & SSL_kECDHE) 
 			{
 			/* XXX: For now, we only support named (not generic) curves.
 			 * In this situation, the serverKeyExchange message has:
 			 * [1 byte CurveType], [2 byte CurveName]
 			 * [1 byte length of encoded point], followed by
 			 * the actual encoded point itself
 			 */
 			*p = NAMED_CURVE_TYPE;
 			p += 1;
 			*p = 0;
 			p += 1;
 			*p = curve_id;
 			p += 1;
 			*p = encodedlen;
 			p += 1;
 			memcpy((unsigned char*)p, 
 			    (unsigned char *)encodedPoint, 
 			    encodedlen);
 			OPENSSL_free(encodedPoint);
 			encodedPoint = NULL;
 			p += encodedlen;
 			}
 #endif
 
 		/* not anonymous */
 		if (pkey != NULL)
 			{
 			/* n is the length of the params, they start at &(d[4])
 			 * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
 			if (pkey->type == EVP_PKEY_RSA)
 				{
 				q=md_buf;
 				j=0;
 				for (num=2; num > 0; num--)
 					{
 					EVP_MD_CTX_set_flags(&md_ctx,
 						EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 					EVP_DigestInit_ex(&md_ctx,(num == 2)
 						?s->ctx->md5:s->ctx->sha1, NULL);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(d[4]),n);
 					EVP_DigestFinal_ex(&md_ctx,q,
 						(unsigned int *)&i);
 					q+=i;
 					j+=i;
 					}
 				if (RSA_sign(NID_md5_sha1, md_buf, j,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0)
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
 					goto err;
 					}
 				s2n(u,p);
 				n+=u+2;
 				}
 			else
 #endif
 #if !defined(OPENSSL_NO_DSA)
 				if (pkey->type == EVP_PKEY_DSA)
 				{
 				/* lets do DSS */
 				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
 				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(d[4]),n);
 				if (!EVP_SignFinal(&md_ctx,&(p[2]),
 					(unsigned int *)&i,pkey))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
 					goto err;
 					}
 				s2n(i,p);
 				n+=i+2;
 				}
 			else
 #endif
 #if !defined(OPENSSL_NO_ECDSA)
 				if (pkey->type == EVP_PKEY_EC)
 				{
 				/* let's do ECDSA */
 				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
 				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(d[4]),n);
 				if (!EVP_SignFinal(&md_ctx,&(p[2]),
 					(unsigned int *)&i,pkey))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
 					goto err;
 					}
 				s2n(i,p);
 				n+=i+2;
 				}
 			else
 #endif
 				{
 				/* Is this error check actually needed? */
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
 				goto f_err;
 				}
 			}
 
 		*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	s->state = SSL3_ST_SW_KEY_EXCH_B;
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 #ifndef OPENSSL_NO_ECDH
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	BN_CTX_free(bn_ctx);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_send_certificate_request(SSL *s)
 	{
 	unsigned char *p,*d;
 	int i,j,nl,off,n;
 	STACK_OF(X509_NAME) *sk=NULL;
 	X509_NAME *name;
 	BUF_MEM *buf;
 
 	if (s->state == SSL3_ST_SW_CERT_REQ_A)
 		{
 		buf=s->init_buf;
 
 		d=p=(unsigned char *)&(buf->data[4]);
 
 		/* get the list of acceptable cert types */
 		p++;
 		n=ssl3_get_req_cert_type(s,p);
 		d[0]=n;
 		p+=n;
 		n++;
 
 		off=n;
 		p+=2;
 		n+=2;
 
 		sk=SSL_get_client_CA_list(s);
 		nl=0;
 		if (sk != NULL)
 			{
 			for (i=0; idata[4+n]);
 				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 					{
 					s2n(j,p);
 					i2d_X509_NAME(name,&p);
 					n+=2+j;
 					nl+=2+j;
 					}
 				else
 					{
 					d=p;
 					i2d_X509_NAME(name,&p);
 					j-=2; s2n(j,d); j+=2;
 					n+=j;
 					nl+=j;
 					}
 				}
 			}
 		/* else no CA names */
 		p=(unsigned char *)&(buf->data[4+off]);
 		s2n(nl,p);
 
 		d=(unsigned char *)buf->data;
 		*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 
 		s->init_num=n+4;
 		s->init_off=0;
 #ifdef NETSCAPE_HANG_BUG
 		if (!BUF_MEM_grow_clean(buf, s->init_num + 4))
 			{
 			SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
 			goto err;
 			}
 		p=(unsigned char *)s->init_buf->data + s->init_num;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 		s->init_num += 4;
 #endif
 
 		s->state = SSL3_ST_SW_CERT_REQ_B;
 		}
 
 	/* SSL3_ST_SW_CERT_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_client_key_exchange(SSL *s)
 	{
 	int i,al,ok;
 	long n;
 	unsigned long l;
 	unsigned char *p;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	BIGNUM *pub=NULL;
 	DH *dh_srvr;
 #endif
 #ifndef OPENSSL_NO_KRB5
         KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *srvr_ecdh = NULL;
 	EVP_PKEY *clnt_pub_pkey = NULL;
 	EC_POINT *clnt_ecpoint = NULL;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_KEY_EXCH_A,
 		SSL3_ST_SR_KEY_EXCH_B,
 		SSL3_MT_CLIENT_KEY_EXCHANGE,
 		2048, /* ??? */
 		&ok);
 
 	if (!ok) return((int)n);
 	p=(unsigned char *)s->init_msg;
 
 	l=s->s3->tmp.new_cipher->algorithms;
 
 #ifndef OPENSSL_NO_RSA
 	if (l & SSL_kRSA)
 		{
 		unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
 		int decrypt_len;
 		unsigned char decrypt_good, version_good;
 
 		/* FIX THIS UP EAY EAY EAY EAY */
 		if (s->s3->tmp.use_rsa_tmp)
 			{
 			if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
 				rsa=s->cert->rsa_tmp;
 			/* Don't do a callback because rsa_tmp should
 			 * be sent already */
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY);
 				goto f_err;
 
 				}
 			}
 		else
 			{
 			pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
 			if (	(pkey == NULL) ||
 				(pkey->type != EVP_PKEY_RSA) ||
 				(pkey->pkey.rsa == NULL))
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
 				goto f_err;
 				}
 			rsa=pkey->pkey.rsa;
 			}
 
 		/* TLS and [incidentally] DTLS, including pre-0.9.8f */
 		if (s->version > SSL3_VERSION &&
 		    s->client_version != DTLS1_BAD_VER)
 			{
 			n2s(p,i);
 			if (n != i+2)
 				{
 				if (!(s->options & SSL_OP_TLS_D5_BUG))
 					{
 					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
 					goto err;
 					}
 				else
 					p-=2;
 				}
 			else
 				n=i;
 			}
 
 		/* We must not leak whether a decryption failure occurs because
 		 * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see
 		 * RFC 2246, section 7.4.7.1). The code follows that advice of
 		 * the TLS RFC and generates a random premaster secret for the
 		 * case that the decrypt fails. See
 		 * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */
 
 		/* should be RAND_bytes, but we cannot work around a failure. */
 		if (RAND_pseudo_bytes(rand_premaster_secret,
 				      sizeof(rand_premaster_secret)) <= 0)
 			goto err;
 		decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
 		ERR_clear_error();
 
 		/* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
 		 * decrypt_good will be 0xff if so and zero otherwise. */
 		decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
 
 		/* If the version in the decrypted pre-master secret is correct
 		 * then version_good will be 0xff, otherwise it'll be zero.
 		 * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
 		 * (http://eprint.iacr.org/2003/052/) exploits the version
 		 * number check as a "bad version oracle". Thus version checks
 		 * are done in constant time and are treated like any other
 		 * decryption error. */
 		version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
 		version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
 
 		/* The premaster secret must contain the same version number as
 		 * the ClientHello to detect version rollback attacks
 		 * (strangely, the protocol does not offer such protection for
 		 * DH ciphersuites). However, buggy clients exist that send the
 		 * negotiated protocol version instead if the server does not
 		 * support the requested protocol version. If
 		 * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
 		if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
 			{
 			unsigned char workaround_good;
 			workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
 			workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
 			version_good |= workaround_good;
 			}
 
 		/* Both decryption and version must be good for decrypt_good
 		 * to remain non-zero (0xff). */
 		decrypt_good &= version_good;
 
 		/* Now copy rand_premaster_secret over p using
 		 * decrypt_good_mask. */
 		for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
 			{
 			p[i] = constant_time_select_8(decrypt_good, p[i],
 						      rand_premaster_secret[i]);
 			}
 
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,
 				p,i);
 		OPENSSL_cleanse(p,i);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DH
 		if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 		{
 		n2s(p,i);
 		if (n != i+2)
 			{
 			if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
 				goto err;
 				}
 			else
 				{
 				p-=2;
 				i=(int)n;
 				}
 			}
 
 		if (n == 0L) /* the parameters are in the cert */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
 			goto f_err;
 			}
 		else
 			{
 			if (s->s3->tmp.dh == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 			else
 				dh_srvr=s->s3->tmp.dh;
 			}
 
 		pub=BN_bin2bn(p,i,NULL);
 		if (pub == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB);
 			goto err;
 			}
 
 		i=DH_compute_key(p,pub,dh_srvr);
 
 		if (i <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 			BN_clear_free(pub);
 			goto err;
 			}
 
 		DH_free(s->s3->tmp.dh);
 		s->s3->tmp.dh=NULL;
 
 		BN_clear_free(pub);
 		pub=NULL;
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,p,i);
 		OPENSSL_cleanse(p,i);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_KRB5
         if (l & SSL_kKRB5)
                 {
                 krb5_error_code		krb5rc;
 		krb5_data		enc_ticket;
 		krb5_data		authenticator;
 		krb5_data		enc_pms;
                 KSSL_CTX		*kssl_ctx = s->kssl_ctx;
 		EVP_CIPHER_CTX		ciph_ctx;
 		EVP_CIPHER		*enc = NULL;
 		unsigned char		iv[EVP_MAX_IV_LENGTH];
 		unsigned char		pms[SSL_MAX_MASTER_KEY_LENGTH
                                                + EVP_MAX_BLOCK_LENGTH];
 		int                     padl, outl;
 		krb5_timestamp		authtime = 0;
 		krb5_ticket_times	ttimes;
+        int kerr = 0;
 
 		EVP_CIPHER_CTX_init(&ciph_ctx);
 
                 if (!kssl_ctx)  kssl_ctx = kssl_ctx_new();
 
 		n2s(p,i);
 		enc_ticket.length = i;
 
 		if (n < (int)enc_ticket.length + 6)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		enc_ticket.data = (char *)p;
 		p+=enc_ticket.length;
 
 		n2s(p,i);
 		authenticator.length = i;
 
 		if (n < (int)(enc_ticket.length + authenticator.length) + 6)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		authenticator.data = (char *)p;
 		p+=authenticator.length;
 
 		n2s(p,i);
 		enc_pms.length = i;
 		enc_pms.data = (char *)p;
 		p+=enc_pms.length;
 
 		/* Note that the length is checked again below,
 		** after decryption
 		*/
 		if(enc_pms.length > sizeof pms)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		if (n != (long)(enc_ticket.length + authenticator.length +
 						enc_pms.length + 6))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
                 if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
 					&kssl_err)) != 0)
                         {
 #ifdef KSSL_DEBUG
                         printf("kssl_sget_tkt rtn %d [%d]\n",
                                 krb5rc, kssl_err.reason);
                         if (kssl_err.text)
                                 printf("kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                                 kssl_err.reason);
                         goto err;
                         }
 
 		/*  Note: no authenticator is not considered an error,
 		**  but will return authtime == 0.
 		*/
 		if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
 					&authtime, &kssl_err)) != 0)
 			{
 #ifdef KSSL_DEBUG
                         printf("kssl_check_authent rtn %d [%d]\n",
                                 krb5rc, kssl_err.reason);
                         if (kssl_err.text)
                                 printf("kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                                 kssl_err.reason);
                         goto err;
 			}
 
 		if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
                         goto err;
 			}
 
 #ifdef KSSL_DEBUG
                 kssl_ctx_show(kssl_ctx);
 #endif	/* KSSL_DEBUG */
 
 		enc = kssl_map_enc(kssl_ctx->enctype);
                 if (enc == NULL)
                     goto err;
 
 		memset(iv, 0, sizeof iv);	/* per RFC 1510 */
 
 		if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
 			goto err;
 			}
 		if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
 					(unsigned char *)enc_pms.data, enc_pms.length))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		outl += padl;
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
 		    {
 		    /* The premaster secret must contain the same version number as the
 		     * ClientHello to detect version rollback attacks (strangely, the
 		     * protocol does not offer such protection for DH ciphersuites).
 		     * However, buggy clients exist that send random bytes instead of
 		     * the protocol version.
 		     * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. 
 		     * (Perhaps we should have a separate BUG value for the Kerberos cipher)
 		     */
 		    if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
 		        {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_AD_DECODE_ERROR);
-			goto err;
+                kerr = 1;
+                goto kclean;
 			}
 		    }
 
 		EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
                 s->session->master_key_length=
                         s->method->ssl3_enc->generate_master_secret(s,
                                 s->session->master_key, pms, outl);
 
                 if (kssl_ctx->client_princ)
                         {
                         size_t len = strlen(kssl_ctx->client_princ);
                         if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) 
                                 {
                                 s->session->krb5_client_princ_len = len;
                                 memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
                                 }
                         }
 
 
                 /*  Was doing kssl_ctx_free() here,
 		**  but it caused problems for apache.
                 **  kssl_ctx = kssl_ctx_free(kssl_ctx);
                 **  if (s->kssl_ctx)  s->kssl_ctx = NULL;
                 */
-                }
-	else
+
+ kclean:
+        OPENSSL_cleanse(pms, sizeof(pms));
+        if (kerr)
+            goto err;
+    } else
 #endif	/* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 		if ((l & SSL_kECDH) || (l & SSL_kECDHE))
 		{
 		int ret = 1;
 		int field_size = 0;
 		const EC_KEY   *tkey;
 		const EC_GROUP *group;
 		const BIGNUM *priv_key;
 
                 /* initialize structures for server's ECDH key pair */
 		if ((srvr_ecdh = EC_KEY_new()) == NULL) 
 			{
                 	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
                 	goto err;
 			}
 
 		/* Let's get server private key and group information */
 		if (l & SSL_kECDH) 
 			{ 
                         /* use the certificate */
 			tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
 			}
 		else
 			{
 			/* use the ephermeral values we saved when
 			 * generating the ServerKeyExchange msg.
 			 */
 			tkey = s->s3->tmp.ecdh;
 			}
 
 		group    = EC_KEY_get0_group(tkey);
 		priv_key = EC_KEY_get0_private_key(tkey);
 
 		if (!EC_KEY_set_group(srvr_ecdh, group) ||
 		    !EC_KEY_set_private_key(srvr_ecdh, priv_key))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       ERR_R_EC_LIB);
 			goto err;
 			}
 
 		/* Let's get client's public key */
 		if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
                 if (n == 0L) 
                         {
 			/* Client Publickey was in Client Certificate */
 
 			 if (l & SSL_kECDHE) 
 				 {
 				 al=SSL_AD_HANDSHAKE_FAILURE;
 				 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				 goto f_err;
 				 }
                         if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
 			    == NULL) || 
 			    (clnt_pub_pkey->type != EVP_PKEY_EC))
                         	{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates
 				 * so this branch (n == 0L) of the code is
 				 * never executed. When that support is
 				 * added, we ought to ensure the key 
 				 * received in the certificate is 
 				 * authorized for key agreement.
 				 * ECDH_compute_key implicitly checks that
 				 * the two ECDH shares are for the same
 				 * group.
 				 */
                            	al=SSL_AD_HANDSHAKE_FAILURE;
                            	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
                            	goto f_err;
                            	}
 
 			if (EC_POINT_copy(clnt_ecpoint,
 			    EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_EC_LIB);
 				goto err;
 				}
                         ret = 2; /* Skip certificate verify processing */
                         }
                 else
                         {
 			/* Get client's public key from encoded point
 			 * in the ClientKeyExchange message.
 			 */
 			if ((bn_ctx = BN_CTX_new()) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
                         /* Get encoded point length */
                         i = *p; 
 			p += 1;
 			if (n != 1 + i)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
                         if (EC_POINT_oct2point(group, 
 			    clnt_ecpoint, p, i, bn_ctx) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
                         /* p is pointing to somewhere in the buffer
                          * currently, so set it to the start 
                          */ 
                         p=(unsigned char *)s->init_buf->data;
                         }
 
 		/* Compute the shared pre-master secret */
 		field_size = EC_GROUP_get_degree(group);
 		if (field_size <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, 
 			       ERR_R_ECDH_LIB);
 			goto err;
 			}
 		i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
                 if (i <= 0)
                         {
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_ECDH_LIB);
                         goto err;
                         }
 
 		EVP_PKEY_free(clnt_pub_pkey);
 		EC_POINT_free(clnt_ecpoint);
 		if (srvr_ecdh != NULL) 
 			EC_KEY_free(srvr_ecdh);
 		BN_CTX_free(bn_ctx);
 
 		/* Compute the master secret */
                 s->session->master_key_length = s->method->ssl3_enc-> \
 		    generate_master_secret(s, s->session->master_key, p, i);
 		
                 OPENSSL_cleanse(p, i);
                 return (ret);
 		}
 	else
 #endif
 		{
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_UNKNOWN_CIPHER_TYPE);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
 err:
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EVP_PKEY_free(clnt_pub_pkey);
 	EC_POINT_free(clnt_ecpoint);
 	if (srvr_ecdh != NULL) 
 		EC_KEY_free(srvr_ecdh);
 	BN_CTX_free(bn_ctx);
 #endif
 	return(-1);
 	}
 
 int ssl3_get_cert_verify(SSL *s)
 	{
 	EVP_PKEY *pkey=NULL;
 	unsigned char *p;
 	int al,ok,ret=0;
 	long n;
 	int type=0,i,j;
 	X509 *peer;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_VRFY_A,
 		SSL3_ST_SR_CERT_VRFY_B,
 		-1,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if (s->session->peer != NULL)
 		{
 		peer=s->session->peer;
 		pkey=X509_get_pubkey(peer);
 		type=X509_certificate_type(peer,pkey);
 		}
 	else
 		{
 		peer=NULL;
 		pkey=NULL;
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
 		{
 		s->s3->tmp.reuse_message=1;
 		if (peer != NULL)
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
 			goto f_err;
 			}
 		ret=1;
 		goto end;
 		}
 
 	if (peer == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	if (!(type & EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		goto f_err;
 		}
 
 	if (s->s3->change_cipher_spec)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	/* we now have a signature that we need to verify */
 	p=(unsigned char *)s->init_msg;
 	n2s(p,i);
 	n-=2;
 	if (i > n)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
 		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
 	j=EVP_PKEY_size(pkey);
 	if ((i > j) || (n > j) || (n <= 0))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
 		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_RSA 
 	if (pkey->type == EVP_PKEY_RSA)
 		{
 		i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
 			MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, 
 							pkey->pkey.rsa);
 		if (i < 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
 			goto f_err;
 			}
 		if (i == 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DSA
 		if (pkey->type == EVP_PKEY_DSA)
 		{
 		j=DSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		if (pkey->type == EVP_PKEY_EC)
 		{
 		j=ECDSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
 			    SSL_R_BAD_ECDSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
 		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
 		goto f_err;
 		}
 
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 end:
 	EVP_PKEY_free(pkey);
 	return(ret);
 	}
 
 int ssl3_get_client_certificate(SSL *s)
 	{
 	int i,ok,al,ret= -1;
 	X509 *x=NULL;
 	unsigned long l,nc,llen,n;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if	(s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
 		{
 		if (	(s->verify_mode & SSL_VERIFY_PEER) &&
 			(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		/* If tls asked for a client cert, the client must return a 0 list */
 		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&p,l);
 		if (x == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto err;
 			}
 		if (p != (q+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		}
 
 	if (sk_X509_num(sk) <= 0)
 		{
 		/* TLS does not mind 0 certs returned */
 		if (s->version == SSL3_VERSION)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
 			goto f_err;
 			}
 		/* Fail for TLS only if we required a certificate */
 		else if ((s->verify_mode & SSL_VERIFY_PEER) &&
 			 (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		}
 	else
 		{
 		i=ssl_verify_cert_chain(s,sk);
 		if (i <= 0)
 			{
 			al=ssl_verify_alarm_type(s->verify_result);
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
 			goto f_err;
 			}
 		}
 
 	if (s->session->peer != NULL) /* This should not be needed */
 		X509_free(s->session->peer);
 	s->session->peer=sk_X509_shift(sk);
 	s->session->verify_result = s->verify_result;
 
 	/* With the current implementation, sess_cert will always be NULL
 	 * when we arrive here. */
 	if (s->session->sess_cert == NULL)
 		{
 		s->session->sess_cert = ssl_sess_cert_new();
 		if (s->session->sess_cert == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	if (s->session->sess_cert->cert_chain != NULL)
 		sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
 	s->session->sess_cert->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does *not* include the
 	 * peer's own certificate, while we do include it in s3_clnt.c */
 
 	sk=NULL;
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (x != NULL) X509_free(x);
 	if (sk != NULL) sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_send_server_certificate(SSL *s)
 	{
 	unsigned long l;
 	X509 *x;
 
 	if (s->state == SSL3_ST_SW_CERT_A)
 		{
 		x=ssl_get_server_send_cert(s);
 		if (x == NULL &&
                         /* VRS: allow null cert if auth == KRB5 */
                         (s->s3->tmp.new_cipher->algorithms
                                 & (SSL_MKEY_MASK|SSL_AUTH_MASK))
                         != (SSL_aKRB5|SSL_kKRB5))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
 			return(0);
 			}
 
 		l=ssl3_output_cert_chain(s,x);
 		s->state=SSL3_ST_SW_CERT_B;
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_CERT_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 
 #ifndef OPENSSL_NO_ECDH
 /* This is the complement of curve_id2nid in s3_clnt.c. */
 static int nid2curve_id(int nid)
 {
 	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
 	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
 	switch (nid) {
 	case NID_sect163k1: /* sect163k1 (1) */
 		return 1;
 	case NID_sect163r1: /* sect163r1 (2) */
 		return 2;
 	case NID_sect163r2: /* sect163r2 (3) */
 		return 3;
 	case NID_sect193r1: /* sect193r1 (4) */ 
 		return 4;
 	case NID_sect193r2: /* sect193r2 (5) */ 
 		return 5;
 	case NID_sect233k1: /* sect233k1 (6) */
 		return 6;
 	case NID_sect233r1: /* sect233r1 (7) */ 
 		return 7;
 	case NID_sect239k1: /* sect239k1 (8) */ 
 		return 8;
 	case NID_sect283k1: /* sect283k1 (9) */
 		return 9;
 	case NID_sect283r1: /* sect283r1 (10) */ 
 		return 10;
 	case NID_sect409k1: /* sect409k1 (11) */ 
 		return 11;
 	case NID_sect409r1: /* sect409r1 (12) */
 		return 12;
 	case NID_sect571k1: /* sect571k1 (13) */ 
 		return 13;
 	case NID_sect571r1: /* sect571r1 (14) */ 
 		return 14;
 	case NID_secp160k1: /* secp160k1 (15) */
 		return 15;
 	case NID_secp160r1: /* secp160r1 (16) */ 
 		return 16;
 	case NID_secp160r2: /* secp160r2 (17) */ 
 		return 17;
 	case NID_secp192k1: /* secp192k1 (18) */
 		return 18;
 	case NID_X9_62_prime192v1: /* secp192r1 (19) */ 
 		return 19;
 	case NID_secp224k1: /* secp224k1 (20) */ 
 		return 20;
 	case NID_secp224r1: /* secp224r1 (21) */
 		return 21;
 	case NID_secp256k1: /* secp256k1 (22) */ 
 		return 22;
 	case NID_X9_62_prime256v1: /* secp256r1 (23) */ 
 		return 23;
 	case NID_secp384r1: /* secp384r1 (24) */
 		return 24;
 	case NID_secp521r1:  /* secp521r1 (25) */	
 		return 25;
 	default:
 		return 0;
 	}
 }
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_send_newsession_ticket(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
 		{
 		unsigned char *p, *senc, *macstart;
 		int len, slen;
 		unsigned int hlen;
 		EVP_CIPHER_CTX ctx;
 		HMAC_CTX hctx;
 		SSL_CTX *tctx = s->initial_ctx;
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char key_name[16];
 
 		/* get session encoding length */
 		slen = i2d_SSL_SESSION(s->session, NULL);
 		/* Some length values are 16 bits, so forget it if session is
  		 * too long
  		 */
 		if (slen > 0xFF00)
 			return -1;
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (size of message name) + 3 (message length
  		 * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
  		 * 16 (key name) + max_iv_len (iv length) +
  		 * session_length + max_enc_block_size (max encrypted session
  		 * length) + max_md_size (HMAC).
  		 */
 		if (!BUF_MEM_grow(s->init_buf,
 			26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
 			EVP_MAX_MD_SIZE + slen))
 			return -1;
 		senc = OPENSSL_malloc(slen);
 		if (!senc)
 			return -1;
 		p = senc;
 		i2d_SSL_SESSION(s->session, &p);
 
 		p=(unsigned char *)s->init_buf->data;
 		/* do the header */
 		*(p++)=SSL3_MT_NEWSESSION_TICKET;
 		/* Skip message length for now */
 		p += 3;
 		EVP_CIPHER_CTX_init(&ctx);
 		HMAC_CTX_init(&hctx);
 		/* Initialize HMAC and cipher contexts. If callback present
 		 * it does all the work otherwise use generated values
 		 * from parent ctx.
 		 */
 		if (tctx->tlsext_ticket_key_cb)
 			{
 			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
 							 &hctx, 1) < 0)
 				{
 				OPENSSL_free(senc);
 				return -1;
 				}
 			}
 		else
 			{
 			RAND_pseudo_bytes(iv, 16);
 			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
 					tctx->tlsext_tick_aes_key, iv);
 			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
 					tlsext_tick_md(), NULL);
 			memcpy(key_name, tctx->tlsext_tick_key_name, 16);
 			}
 		l2n(s->session->tlsext_tick_lifetime_hint, p);
 		/* Skip ticket length for now */
 		p += 2;
 		/* Output key name */
 		macstart = p;
 		memcpy(p, key_name, 16);
 		p += 16;
 		/* output IV */
 		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
 		p += EVP_CIPHER_CTX_iv_length(&ctx);
 		/* Encrypt session data */
 		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
 		p += len;
 		EVP_EncryptFinal(&ctx, p, &len);
 		p += len;
 		EVP_CIPHER_CTX_cleanup(&ctx);
 
 		HMAC_Update(&hctx, macstart, p - macstart);
 		HMAC_Final(&hctx, p, &hlen);
 		HMAC_CTX_cleanup(&hctx);
 
 		p += hlen;
 		/* Now write out lengths: p points to end of data written */
 		/* Total length */
 		len = p - (unsigned char *)s->init_buf->data;
 		p=(unsigned char *)s->init_buf->data + 1;
 		l2n3(len - 4, p); /* Message length */
 		p += 4;
 		s2n(len - 10, p);  /* Ticket length */
 
 		/* number of bytes to write */
 		s->init_num= len;
 		s->state=SSL3_ST_SW_SESSION_TICKET_B;
 		s->init_off=0;
 		OPENSSL_free(senc);
 		}
 
 	/* SSL3_ST_SW_SESSION_TICKET_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_cert_status(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_CERT_STATUS_A)
 		{
 		unsigned char *p;
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (message type) + 3 (message length) +
  		 * 1 (ocsp response type) + 3 (ocsp response length)
  		 * + (ocsp response)
  		 */
 		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
 			return -1;
 
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_CERTIFICATE_STATUS;
 		/* message length */
 		l2n3(s->tlsext_ocsp_resplen + 4, p);
 		/* status type */
 		*(p++)= s->tlsext_status_type;
 		/* length of OCSP response */
 		l2n3(s->tlsext_ocsp_resplen, p);
 		/* actual response */
 		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
 		/* number of bytes to write */
 		s->init_num = 8 + s->tlsext_ocsp_resplen;
 		s->state=SSL3_ST_SW_CERT_STATUS_B;
 		s->init_off = 0;
 		}
 
 	/* SSL3_ST_SW_CERT_STATUS_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 #endif
Index: releng/8.4/crypto/openssl/ssl/ssl.h
===================================================================
--- releng/8.4/crypto/openssl/ssl/ssl.h	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/ssl.h	(revision 284295)
@@ -1,2149 +1,2150 @@
 /* ssl/ssl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #ifndef HEADER_SSL_H 
 #define HEADER_SSL_H 
 
 #include 
 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #ifndef OPENSSL_NO_BIO
 #include 
 #endif
 #ifndef OPENSSL_NO_DEPRECATED
 #ifndef OPENSSL_NO_X509
 #include 
 #endif
 #include 
 #include 
 #include 
 #endif
 #include 
 #include 
 
 #include 
 #include 
 #include 
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* SSLeay version number for ASN.1 encoding of the session information */
 /* Version 0 - initial version
  * Version 1 - added the optional peer certificate
  */
 #define SSL_SESSION_ASN1_VERSION 0x0001
 
 /* text strings for the ciphers */
 #define SSL_TXT_NULL_WITH_MD5		SSL2_TXT_NULL_WITH_MD5			
 #define SSL_TXT_RC4_128_WITH_MD5	SSL2_TXT_RC4_128_WITH_MD5		
 #define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	
 #define SSL_TXT_RC2_128_CBC_WITH_MD5	SSL2_TXT_RC2_128_CBC_WITH_MD5		
 #define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	
 #define SSL_TXT_IDEA_128_CBC_WITH_MD5	SSL2_TXT_IDEA_128_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_MD5	SSL2_TXT_DES_64_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_SHA	SSL2_TXT_DES_64_CBC_WITH_SHA		
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	
 
 /*    VRS Additional Kerberos5 entries
  */
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA
 #define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5       
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5       
 #define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5
 #define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
 #define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256
 
 #define SSL_MAX_SSL_SESSION_ID_LENGTH		32
 #define SSL_MAX_SID_CTX_LENGTH			32
 
 #define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES	(512/8)
 #define SSL_MAX_KEY_ARG_LENGTH			8
 #define SSL_MAX_MASTER_KEY_LENGTH		48
 
 /* These are used to specify which ciphers to use and not to use */
 #define SSL_TXT_LOW		"LOW"
 #define SSL_TXT_MEDIUM		"MEDIUM"
 #define SSL_TXT_HIGH		"HIGH"
 #define SSL_TXT_FIPS		"FIPS"
 #define SSL_TXT_kFZA		"kFZA"
 #define	SSL_TXT_aFZA		"aFZA"
 #define SSL_TXT_eFZA		"eFZA"
 #define SSL_TXT_FZA		"FZA"
 
 #define	SSL_TXT_aNULL		"aNULL"
 #define	SSL_TXT_eNULL		"eNULL"
 #define	SSL_TXT_NULL		"NULL"
 
 #define SSL_TXT_kKRB5     	"kKRB5"
 #define SSL_TXT_aKRB5     	"aKRB5"
 #define SSL_TXT_KRB5      	"KRB5"
 
 #define SSL_TXT_kRSA		"kRSA"
 #define SSL_TXT_kDHr		"kDHr"
 #define SSL_TXT_kDHd		"kDHd"
 #define SSL_TXT_kEDH		"kEDH"
 #define	SSL_TXT_aRSA		"aRSA"
 #define	SSL_TXT_aDSS		"aDSS"
 #define	SSL_TXT_aDH		"aDH"
 #define	SSL_TXT_DSS		"DSS"
 #define SSL_TXT_DH		"DH"
 #define SSL_TXT_EDH		"EDH"
 #define SSL_TXT_ADH		"ADH"
 #define SSL_TXT_RSA		"RSA"
 #define SSL_TXT_DES		"DES"
 #define SSL_TXT_3DES		"3DES"
 #define SSL_TXT_RC4		"RC4"
 #define SSL_TXT_RC2		"RC2"
 #define SSL_TXT_IDEA		"IDEA"
 #define SSL_TXT_SEED		"SEED"
 #define SSL_TXT_AES		"AES"
 #define SSL_TXT_CAMELLIA	"CAMELLIA"
 #define SSL_TXT_MD5		"MD5"
 #define SSL_TXT_SHA1		"SHA1"
 #define SSL_TXT_SHA		"SHA"
 #define SSL_TXT_EXP		"EXP"
 #define SSL_TXT_EXPORT		"EXPORT"
 #define SSL_TXT_EXP40		"EXPORT40"
 #define SSL_TXT_EXP56		"EXPORT56"
 #define SSL_TXT_SSLV2		"SSLv2"
 #define SSL_TXT_SSLV3		"SSLv3"
 #define SSL_TXT_TLSV1		"TLSv1"
 #define SSL_TXT_ALL		"ALL"
 #define SSL_TXT_ECC		"ECCdraft" /* ECC ciphersuites are not yet official */
 
 /*
  * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
  * ciphers normally not being used.
  * Example: "RC4" will activate all ciphers using RC4 including ciphers
  * without authentication, which would normally disabled by DEFAULT (due
  * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
  * will make sure that it is also disabled in the specific selection.
  * COMPLEMENTOF* identifiers are portable between version, as adjustments
  * to the default cipher setup will also be included here.
  *
  * COMPLEMENTOFDEFAULT does not experience the same special treatment that
  * DEFAULT gets, as only selection is being done and no sorting as needed
  * for DEFAULT.
  */
 #define SSL_TXT_CMPALL		"COMPLEMENTOFALL"
 #define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT"
 
 /* The following cipher list is used by default.
  * It also is substituted when an application-defined cipher list string
  * starts with 'DEFAULT'. */
 #define SSL_DEFAULT_CIPHER_LIST	"AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" /* low priority for RC4 */
 
 /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
 #define SSL_SENT_SHUTDOWN	1
 #define SSL_RECEIVED_SHUTDOWN	2
 
 #ifdef __cplusplus
 }
 #endif
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 #if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
 #define OPENSSL_NO_SSL2
 #endif
 
 #define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
 #define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
 
 /* This is needed to stop compilers complaining about the
  * 'struct ssl_st *' function parameters used to prototype callbacks
  * in SSL_CTX. */
 typedef struct ssl_st *ssl_crock_st;
 
 /* used to hold info on the particular ciphers used */
 typedef struct ssl_cipher_st
 	{
 	int valid;
 	const char *name;		/* text name */
 	unsigned long id;		/* id, 4 bytes, first is version */
 	unsigned long algorithms;	/* what ciphers are used */
 	unsigned long algo_strength;	/* strength and export flags */
 	unsigned long algorithm2;	/* Extra flags */
 	int strength_bits;		/* Number of bits really used */
 	int alg_bits;			/* Number of bits for algorithm */
 	unsigned long mask;		/* used for matching */
 	unsigned long mask_strength;	/* also used for matching */
 	} SSL_CIPHER;
 
 DECLARE_STACK_OF(SSL_CIPHER)
 
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 typedef struct ssl_method_st
 	{
 	int version;
 	int (*ssl_new)(SSL *s);
 	void (*ssl_clear)(SSL *s);
 	void (*ssl_free)(SSL *s);
 	int (*ssl_accept)(SSL *s);
 	int (*ssl_connect)(SSL *s);
 	int (*ssl_read)(SSL *s,void *buf,int len);
 	int (*ssl_peek)(SSL *s,void *buf,int len);
 	int (*ssl_write)(SSL *s,const void *buf,int len);
 	int (*ssl_shutdown)(SSL *s);
 	int (*ssl_renegotiate)(SSL *s);
 	int (*ssl_renegotiate_check)(SSL *s);
 	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
 		max, int *ok);
 	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, 
 		int peek);
 	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
 	int (*ssl_dispatch_alert)(SSL *s);
 	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
 	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
 	SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
 	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
 	int (*ssl_pending)(const SSL *s);
 	int (*num_ciphers)(void);
 	SSL_CIPHER *(*get_cipher)(unsigned ncipher);
 	struct ssl_method_st *(*get_ssl_method)(int version);
 	long (*get_timeout)(void);
 	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
 	int (*ssl_version)(void);
 	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
 	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
 	} SSL_METHOD;
 
 /* Lets make this into an ASN.1 type structure as follows
  * SSL_SESSION_ID ::= SEQUENCE {
  *	version 		INTEGER,	-- structure version number
  *	SSLversion 		INTEGER,	-- SSL version number
  *	Cipher 			OCTET_STRING,	-- the 3 byte cipher ID
  *	Session_ID 		OCTET_STRING,	-- the Session ID
  *	Master_key 		OCTET_STRING,	-- the master key
  *	KRB5_principal		OCTET_STRING	-- optional Kerberos principal
  *	Key_Arg [ 0 ] IMPLICIT	OCTET_STRING,	-- the optional Key argument
  *	Time [ 1 ] EXPLICIT	INTEGER,	-- optional Start Time
  *	Timeout [ 2 ] EXPLICIT	INTEGER,	-- optional Timeout ins seconds
  *	Peer [ 3 ] EXPLICIT	X509,		-- optional Peer Certificate
  *	Session_ID_context [ 4 ] EXPLICIT OCTET_STRING,   -- the Session ID context
  *	Verify_result [ 5 ] EXPLICIT INTEGER    -- X509_V_... code for `Peer'
  *	Compression [6] IMPLICIT ASN1_OBJECT	-- compression OID XXXXX
  *	}
  * Look in ssl/ssl_asn1.c for more details
  * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
  */
 typedef struct ssl_session_st
 	{
 	int ssl_version;	/* what ssl version session info is
 				 * being kept in here? */
 
 	/* only really used in SSLv2 */
 	unsigned int key_arg_length;
 	unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
 	int master_key_length;
 	unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
 	/* session_id - valid? */
 	unsigned int session_id_length;
 	unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
 	/* this is used to determine whether the session is being reused in
 	 * the appropriate context. It is up to the application to set this,
 	 * via SSL_new */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 #ifndef OPENSSL_NO_KRB5
         unsigned int krb5_client_princ_len;
         unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
 #endif /* OPENSSL_NO_KRB5 */
 
 	int not_resumable;
 
 	/* The cert is the certificate used to establish this connection */
 	struct sess_cert_st /* SESS_CERT */ *sess_cert;
 
 	/* This is the cert for the other end.
 	 * On clients, it will be the same as sess_cert->peer_key->x509
 	 * (the latter is not enough as sess_cert is not retained
 	 * in the external representation of sessions, see ssl_asn1.c). */
 	X509 *peer;
 	/* when app_verify_callback accepts a session where the peer's certificate
 	 * is not ok, we must remember the error for session reuse: */
 	long verify_result; /* only for servers */
 
 	int references;
 	long timeout;
 	long time;
 
 	int compress_meth;		/* Need to lookup the method */
 
 	SSL_CIPHER *cipher;
 	unsigned long cipher_id;	/* when ASN.1 loaded, this
 					 * needs to be used to load
 					 * the 'cipher' structure */
 
 	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
 
 	CRYPTO_EX_DATA ex_data; /* application specific data */
 
 	/* These are used to make removal of session-ids more
 	 * efficient and to implement a maximum cache size. */
 	struct ssl_session_st *prev,*next;
 #ifndef OPENSSL_NO_TLSEXT
 	char *tlsext_hostname;
 	/* RFC4507 info */
 	unsigned char *tlsext_tick;	/* Session ticket */
 	size_t	tlsext_ticklen;		/* Session ticket length */	
 	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */
 #endif
 	} SSL_SESSION;
 
 
 #define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
 #define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
 /* Allow initial connection to servers that don't support RI */
 #define SSL_OP_LEGACY_SERVER_CONNECT			0x00000004L
 #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG		0x00000008L
 #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG		0x00000010L
 #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER		0x00000020L
 #define SSL_OP_SAFARI_ECDHE_ECDSA_BUG			0x00000040L
 #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
 #define SSL_OP_TLS_D5_BUG				0x00000100L
 #define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
 
 /* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */
 #define SSL_OP_MSIE_SSLV2_RSA_PADDING			0x0
 
 /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
  * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
  * the workaround is not needed.  Unfortunately some broken SSL/TLS
  * implementations cannot handle it at all, which is why we include
  * it in SSL_OP_ALL. */
 #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */
 
 /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
  *             This used to be 0x000FFFFFL before 0.9.7. */
 #define SSL_OP_ALL					0x00000FFFL
 
 /* DTLS options */
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
 /* Turn on Cookie Exchange (on relevant for servers) */
 #define SSL_OP_COOKIE_EXCHANGE              0x00002000L
 /* Don't use RFC4507 ticket extension */
 #define SSL_OP_NO_TICKET	            0x00004000L
 /* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */
 #define SSL_OP_CISCO_ANYCONNECT		    0x00008000L
 
 /* As server, disallow session resumption on renegotiation */
 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L
 /* Permit unsafe legacy renegotiation */
 #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L
 /* If set, always create a new key when using tmp_ecdh parameters */
 #define SSL_OP_SINGLE_ECDH_USE				0x00080000L
 /* If set, always create a new key when using tmp_dh parameters */
 #define SSL_OP_SINGLE_DH_USE				0x00100000L
 /* Does nothing: retained for compatibiity */
 #define SSL_OP_EPHEMERAL_RSA				0x0
 /* Set on servers to choose the cipher according to the server's
  * preferences */
 #define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L
 /* If set, a server will allow a client to issue a SSLv3.0 version number
  * as latest version supported in the premaster secret, even when TLSv1.0
  * (version 3.1) was announced in the client hello. Normally this is
  * forbidden to prevent version rollback attacks. */
 #define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L
 
 #define SSL_OP_NO_SSLv2					0x01000000L
 #define SSL_OP_NO_SSLv3					0x02000000L
 #define SSL_OP_NO_TLSv1					0x04000000L
 
 /* The next flag deliberately changes the ciphertest, this is a check
  * for the PKCS#1 attack */
 #define SSL_OP_PKCS1_CHECK_1				0x08000000L
 #define SSL_OP_PKCS1_CHECK_2				0x10000000L
 #define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L
 
 
 /* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
  * when just a single record has been written): */
 #define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
 /* Make it possible to retry SSL_write() with changed buffer location
  * (buffer contents must stay the same!); this is not the default to avoid
  * the misconception that non-blocking SSL_write() behaves like
  * non-blocking write(): */
 #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
 /* Never bother the application with retries if the transport
  * is blocking: */
 #define SSL_MODE_AUTO_RETRY 0x00000004L
 /* Don't attempt to automatically build certificate chain */
 #define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
 /* Send TLS_FALLBACK_SCSV in the ClientHello.
  * To be set only by applications that reconnect with a downgraded protocol
  * version; see draft-ietf-tls-downgrade-scsv-00 for details.
  *
  * DO NOT ENABLE THIS if your application attempts a normal handshake.
  * Only use this in explicit fallback retries, following the guidance
  * in draft-ietf-tls-downgrade-scsv-00.
  */
 #define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L
 
 
 /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
  * they cannot be used to clear bits. */
 
 #define SSL_CTX_set_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_CTX_clear_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_CTX_get_options(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
 #define SSL_set_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_clear_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_get_options(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
 
 #define SSL_CTX_set_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
 #define SSL_CTX_clear_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_CTX_get_mode(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
 #define SSL_clear_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_set_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
 #define SSL_get_mode(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
 #define SSL_set_mtu(ssl, mtu) \
         SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
 
 #define SSL_get_secure_renegotiation_support(ssl) \
 	SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
 
 void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 #define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 #define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 
 
 
 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
 #else
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
 #endif
 
 #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
 
 /* This callback type is used inside SSL_CTX, SSL, and in the functions that set
  * them. It is used to override the generation of SSL/TLS session IDs in a
  * server. Return value should be zero on an error, non-zero to proceed. Also,
  * callbacks should themselves check if the id they generate is unique otherwise
  * the SSL handshake will fail with an error - callbacks can do this using the
  * 'ssl' value they're passed by;
  *      SSL_has_matching_session_id(ssl, id, *id_len)
  * The length value passed in is set at the maximum size the session ID can be.
  * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
  * can alter this length to be less if desired, but under SSLv2 session IDs are
  * supposed to be fixed at 16 bytes so the id will be padded after the callback
  * returns in this case. It is also an error for the callback to set the size to
  * zero. */
 typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len);
 
 typedef struct ssl_comp_st
 	{
 	int id;
 	const char *name;
 #ifndef OPENSSL_NO_COMP
 	COMP_METHOD *method;
 #else
 	char *method;
 #endif
 	} SSL_COMP;
 
 DECLARE_STACK_OF(SSL_COMP)
 
 struct ssl_ctx_st
 	{
 	SSL_METHOD *method;
 
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	/* same as above but sorted for lookup */
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	struct x509_store_st /* X509_STORE */ *cert_store;
 	struct lhash_st /* LHASH */ *sessions;	/* a set of SSL_SESSIONs */
 	/* Most session-ids that will be cached, default is
 	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
 	unsigned long session_cache_size;
 	struct ssl_session_st *session_cache_head;
 	struct ssl_session_st *session_cache_tail;
 
 	/* This can have one of 2 values, ored together,
 	 * SSL_SESS_CACHE_CLIENT,
 	 * SSL_SESS_CACHE_SERVER,
 	 * Default is SSL_SESSION_CACHE_SERVER, which means only
 	 * SSL_accept which cache SSL_SESSIONS. */
 	int session_cache_mode;
 
 	/* If timeout is not 0, it is the default timeout value set
 	 * when SSL_new() is called.  This has been put in to make
 	 * life easier to set things up */
 	long session_timeout;
 
 	/* If this callback is not null, it will be called each
 	 * time a session id is added to the cache.  If this function
 	 * returns 1, it means that the callback will do a
 	 * SSL_SESSION_free() when it has finished using it.  Otherwise,
 	 * on 0, it means the callback has finished with it.
 	 * If remove_session_cb is not null, it will be called when
 	 * a session-id is removed from the cache.  After the call,
 	 * OpenSSL will SSL_SESSION_free() it. */
 	int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
 	void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
 	SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
 		unsigned char *data,int len,int *copy);
 
 	struct
 		{
 		int sess_connect;	/* SSL new conn - started */
 		int sess_connect_renegotiate;/* SSL reneg - requested */
 		int sess_connect_good;	/* SSL new conne/reneg - finished */
 		int sess_accept;	/* SSL new accept - started */
 		int sess_accept_renegotiate;/* SSL reneg - requested */
 		int sess_accept_good;	/* SSL accept/reneg - finished */
 		int sess_miss;		/* session lookup misses  */
 		int sess_timeout;	/* reuse attempt on timeouted session */
 		int sess_cache_full;	/* session removed due to full cache */
 		int sess_hit;		/* session reuse actually done */
 		int sess_cb_hit;	/* session-id that was not
 					 * in the cache was
 					 * passed back via the callback.  This
 					 * indicates that the application is
 					 * supplying session-id's from other
 					 * processes - spooky :-) */
 		} stats;
 
 	int references;
 
 	/* if defined, these override the X509_verify_cert() calls */
 	int (*app_verify_callback)(X509_STORE_CTX *, void *);
 	void *app_verify_arg;
 	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
 	 * ('app_verify_callback' was called with just one argument) */
 
 	/* Default password callback. */
 	pem_password_cb *default_passwd_callback;
 
 	/* Default password callback user data. */
 	void *default_passwd_callback_userdata;
 
 	/* get client cert callback */
 	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 
     /* cookie generate callback */
     int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int *cookie_len);
 
     /* verify cookie callback */
     int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int cookie_len);
 
 	CRYPTO_EX_DATA ex_data;
 
 	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
 	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
 	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
 
 	STACK_OF(X509) *extra_certs;
 	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
 
 
 	/* Default values used when no per-SSL value is defined follow */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
 
 	/* what we put in client cert requests */
 	STACK_OF(X509_NAME) *client_CA;
 
 
 	/* Default values to use in SSL structures follow (these are copied by SSL_new) */
 
 	unsigned long options;
 	unsigned long mode;
 	long max_cert_list;
 
 	struct cert_st /* CERT */ *cert;
 	int read_ahead;
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int verify_mode;
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	int quiet_shutdown;
 
 #ifndef OPENSSL_ENGINE
 	/* Engine to pass requests for client certs to
 	 */
 	ENGINE *client_cert_engine;
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions servername callback */
 	int (*tlsext_servername_callback)(SSL*, int *, void *);
 	void *tlsext_servername_arg;
 	/* RFC 4507 session ticket keys */
 	unsigned char tlsext_tick_key_name[16];
 	unsigned char tlsext_tick_hmac_key[16];
 	unsigned char tlsext_tick_aes_key[16];
 	/* Callback to support customisation of ticket key setting */
 	int (*tlsext_ticket_key_cb)(SSL *ssl,
 					unsigned char *name, unsigned char *iv,
 					EVP_CIPHER_CTX *ectx,
 					HMAC_CTX *hctx, int enc);
 
 	/* certificate status request info */
 	/* Callback for status request */
 	int (*tlsext_status_cb)(SSL *ssl, void *arg);
 	void *tlsext_status_arg;
 #endif
 
 	};
 
 #define SSL_SESS_CACHE_OFF			0x0000
 #define SSL_SESS_CACHE_CLIENT			0x0001
 #define SSL_SESS_CACHE_SERVER			0x0002
 #define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
 #define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
 /* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
 #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
 #define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200
 #define SSL_SESS_CACHE_NO_INTERNAL \
 	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
 
   struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
 #define SSL_CTX_sess_number(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
 #define SSL_CTX_sess_connect(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
 #define SSL_CTX_sess_connect_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
 #define SSL_CTX_sess_connect_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
 #define SSL_CTX_sess_accept_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
 #define SSL_CTX_sess_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
 #define SSL_CTX_sess_cb_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
 #define SSL_CTX_sess_misses(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
 #define SSL_CTX_sess_timeouts(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
 #define SSL_CTX_sess_cache_full(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
 SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
 #endif
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
 
 #define SSL_NOTHING	1
 #define SSL_WRITING	2
 #define SSL_READING	3
 #define SSL_X509_LOOKUP	4
 
 /* These will only be used when doing non-blocking IO */
 #define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
 #define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
 #define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
 #define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
 
 struct ssl_st
 	{
 	/* protocol version
 	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
 	 */
 	int version;
 	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
 
 	SSL_METHOD *method; /* SSLv3 */
 
 	/* There are 2 BIO's even though they are normally both the
 	 * same.  This is so data can be read and written to different
 	 * handlers */
 
 #ifndef OPENSSL_NO_BIO
 	BIO *rbio; /* used by SSL_read */
 	BIO *wbio; /* used by SSL_write */
 	BIO *bbio; /* used during session-id reuse to concatenate
 		    * messages */
 #else
 	char *rbio; /* used by SSL_read */
 	char *wbio; /* used by SSL_write */
 	char *bbio;
 #endif
 	/* This holds a variable that indicates what we were doing
 	 * when a 0 or -1 is returned.  This is needed for
 	 * non-blocking IO so we know what request needs re-doing when
 	 * in SSL_accept or SSL_connect */
 	int rwstate;
 
 	/* true when we are actually in SSL_accept() or SSL_connect() */
 	int in_handshake;
 	int (*handshake_func)(SSL *);
 
 	/* Imagine that here's a boolean member "init" that is
 	 * switched as soon as SSL_set_{accept/connect}_state
 	 * is called for the first time, so that "state" and
 	 * "handshake_func" are properly initialized.  But as
 	 * handshake_func is == 0 until then, we use this
 	 * test instead of an "init" member.
 	 */
 
 	int server;	/* are we the server side? - mostly used by SSL_clear*/
 
 	int new_session;/* 1 if we are to use a new session.
 	                 * 2 if we are a server and are inside a handshake
 	                 *   (i.e. not just sending a HelloRequest)
 	                 * NB: For servers, the 'new' session may actually be a previously
 	                 * cached session or even the previous session unless
 	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 	int quiet_shutdown;/* don't send shutdown packets */
 	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
 			 * for received */
 	int state;	/* where we are */
 	int rstate;	/* where we are when reading */
 
 	BUF_MEM *init_buf;	/* buffer used during init */
 	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */
 	int init_num;		/* amount read/written */
 	int init_off;		/* amount read/written */
 
 	/* used internally to point at a raw packet */
 	unsigned char *packet;
 	unsigned int packet_length;
 
 	struct ssl2_state_st *s2; /* SSLv2 variables */
 	struct ssl3_state_st *s3; /* SSLv3 variables */
 	struct dtls1_state_st *d1; /* DTLSv1 variables */
 
 	int read_ahead;		/* Read as many input bytes as possible
 	               	 	 * (for non-blocking reads) */
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int hit;		/* reusing a previous session */
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	/* crypto */
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	/* These are the ones being used, the ones in SSL_SESSION are
 	 * the ones to be 'copied' into these ones */
 
 	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
 	const EVP_MD *read_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *expand;			/* uncompress */
 #else
 	char *expand;
 #endif
 
 	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
 	const EVP_MD *write_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *compress;			/* compression */
 #else
 	char *compress;	
 #endif
 
 	/* session info */
 
 	/* client cert? */
 	/* This is used to hold the server certificate used */
 	struct cert_st /* CERT */ *cert;
 
 	/* the session_id_context is used to ensure sessions are only reused
 	 * in the appropriate context */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 	/* This can also be in the session once a session is established */
 	SSL_SESSION *session;
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	/* Used in SSL2 and SSL3 */
 	int verify_mode;	/* 0 don't care about verify failure.
 				 * 1 fail if verify fails */
 	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
 
 	int error;		/* error bytes to be written */
 	int error_code;		/* actual code */
 
 #ifndef OPENSSL_NO_KRB5
 	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
 #endif	/* OPENSSL_NO_KRB5 */
 
 	SSL_CTX *ctx;
 	/* set this flag to 1 and a sleep(1) is put into all SSL_read()
 	 * and SSL_write() calls, good for nbio debuging :-) */
 	int debug;	
 
 	/* extra application data */
 	long verify_result;
 	CRYPTO_EX_DATA ex_data;
 
 	/* for server side, keep the list of CA_dn we can use */
 	STACK_OF(X509_NAME) *client_CA;
 
 	int references;
 	unsigned long options; /* protocol behaviour */
 	unsigned long mode; /* API behaviour */
 	long max_cert_list;
 	int first_packet;
 	int client_version;	/* what was passed, used for
 				 * SSLv3/TLS rollback check */
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extension debug callback */
 	void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
 					unsigned char *data, int len,
 					void *arg);
 	void *tlsext_debug_arg;
 	char *tlsext_hostname;
 	int servername_done;   /* no further mod of servername 
 	                          0 : call the servername extension callback.
 	                          1 : prepare 2, allow last ack just after in server callback.
 	                          2 : don't call servername callback, no ack in server hello
 	                       */
 	/* certificate status request info */
 	/* Status type or -1 if no status type */
 	int tlsext_status_type;
 	/* Expect OCSP CertificateStatus message */
 	int tlsext_status_expected;
 	/* OCSP status request only */
 	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
 	X509_EXTENSIONS *tlsext_ocsp_exts;
 	/* OCSP response received or to be sent */
 	unsigned char *tlsext_ocsp_resp;
 	int tlsext_ocsp_resplen;
 
 	/* RFC4507 session ticket expected to be received or sent */
 	int tlsext_ticket_expected;
 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
 #define session_ctx initial_ctx
 #else
 #define session_ctx ctx
 #endif
 	};
 
 #ifdef __cplusplus
 }
 #endif
 
 #include 
 #include 
 #include  /* This is mostly sslv3 with a few tweaks */
 #include  /* Datagram TLS */
 #include 
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* compatibility */
 #define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
 #define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
 #define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
 #define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
 #define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
 #define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
 
 /* The following are the possible values for ssl->state are are
  * used to indicate where we are up to in the SSL connection establishment.
  * The macros that follow are about the only things you should need to use
  * and even then, only when using non-blocking IO.
  * It can also be useful to work out where you were when the connection
  * failed */
 
 #define SSL_ST_CONNECT			0x1000
 #define SSL_ST_ACCEPT			0x2000
 #define SSL_ST_MASK			0x0FFF
 #define SSL_ST_INIT			(SSL_ST_CONNECT|SSL_ST_ACCEPT)
 #define SSL_ST_BEFORE			0x4000
 #define SSL_ST_OK			0x03
 #define SSL_ST_RENEGOTIATE		(0x04|SSL_ST_INIT)
 
 #define SSL_CB_LOOP			0x01
 #define SSL_CB_EXIT			0x02
 #define SSL_CB_READ			0x04
 #define SSL_CB_WRITE			0x08
 #define SSL_CB_ALERT			0x4000 /* used in callback */
 #define SSL_CB_READ_ALERT		(SSL_CB_ALERT|SSL_CB_READ)
 #define SSL_CB_WRITE_ALERT		(SSL_CB_ALERT|SSL_CB_WRITE)
 #define SSL_CB_ACCEPT_LOOP		(SSL_ST_ACCEPT|SSL_CB_LOOP)
 #define SSL_CB_ACCEPT_EXIT		(SSL_ST_ACCEPT|SSL_CB_EXIT)
 #define SSL_CB_CONNECT_LOOP		(SSL_ST_CONNECT|SSL_CB_LOOP)
 #define SSL_CB_CONNECT_EXIT		(SSL_ST_CONNECT|SSL_CB_EXIT)
 #define SSL_CB_HANDSHAKE_START		0x10
 #define SSL_CB_HANDSHAKE_DONE		0x20
 
 /* Is the SSL_connection established? */
 #define SSL_get_state(a)		SSL_state(a)
 #define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
 #define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
 #define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
 #define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
 #define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
  * you should not need these */
 #define SSL_ST_READ_HEADER			0xF0
 #define SSL_ST_READ_BODY			0xF1
 #define SSL_ST_READ_DONE			0xF2
 
 /* Obtain latest Finished message
  *   -- that we sent (SSL_get_finished)
  *   -- that we expected from peer (SSL_get_peer_finished).
  * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
 size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
 size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 
 /* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
  * are 'ored' with SSL_VERIFY_PEER if they are desired */
 #define SSL_VERIFY_NONE			0x00
 #define SSL_VERIFY_PEER			0x01
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
 #define SSL_VERIFY_CLIENT_ONCE		0x04
 
 #define OpenSSL_add_ssl_algorithms()	SSL_library_init()
 #define SSLeay_add_ssl_algorithms()	SSL_library_init()
 
 /* this is for backward compatibility */
 #if 0 /* NEW_SSLEAY */
 #define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
 #define SSL_set_pref_cipher(c,n)	SSL_set_cipher_list(c,n)
 #define SSL_add_session(a,b)            SSL_CTX_add_session((a),(b))
 #define SSL_remove_session(a,b)		SSL_CTX_remove_session((a),(b))
 #define SSL_flush_sessions(a,b)		SSL_CTX_flush_sessions((a),(b))
 #endif
 /* More backward compatibility */
 #define SSL_get_cipher(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_cipher_bits(s,np) \
 		SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
 #define SSL_get_cipher_version(s) \
 		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
 #define SSL_get_cipher_name(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_time(a)		SSL_SESSION_get_time(a)
 #define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
 #define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
 #define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
 
 #if 1 /*SSLEAY_MACROS*/
 #define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
 #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
 #define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
 	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
 #define PEM_read_bio_SSL_SESSION(bp,x,cb,u) PEM_ASN1_read_bio_of(SSL_SESSION,d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,cb,u)
 #define PEM_write_SSL_SESSION(fp,x) \
 	PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
 		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_SSL_SESSION(bp,x) \
 	PEM_ASN1_write_bio_of(SSL_SESSION,i2d_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,NULL,NULL,0,NULL,NULL)
 #endif
 
 #define SSL_AD_REASON_OFFSET		1000
 /* These alert types are for SSLv3 and TLSv1 */
 #define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
 #define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
 #define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
 #define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
 #define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
 #define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
 #define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
 #define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
 #define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
 #define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
 #define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
 #define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
 #define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
 #define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
 #define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
 #define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
 #define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
 #define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
 #define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */
 #define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
 #define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
 #define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
 #define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
 #define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION
 #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 #define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME
 #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY	TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
 #define SSL_AD_INAPPROPRIATE_FALLBACK	TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */
 
 #define SSL_ERROR_NONE			0
 #define SSL_ERROR_SSL			1
 #define SSL_ERROR_WANT_READ		2
 #define SSL_ERROR_WANT_WRITE		3
 #define SSL_ERROR_WANT_X509_LOOKUP	4
 #define SSL_ERROR_SYSCALL		5 /* look at error stack/return value/errno */
 #define SSL_ERROR_ZERO_RETURN		6
 #define SSL_ERROR_WANT_CONNECT		7
 #define SSL_ERROR_WANT_ACCEPT		8
 
 #define SSL_CTRL_NEED_TMP_RSA			1
 #define SSL_CTRL_SET_TMP_RSA			2
 #define SSL_CTRL_SET_TMP_DH			3
 #define SSL_CTRL_SET_TMP_ECDH			4
 #define SSL_CTRL_SET_TMP_RSA_CB			5
 #define SSL_CTRL_SET_TMP_DH_CB			6
 #define SSL_CTRL_SET_TMP_ECDH_CB		7
 
 #define SSL_CTRL_GET_SESSION_REUSED		8
 #define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9
 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10
 #define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11
 #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12
 #define SSL_CTRL_GET_FLAGS			13
 #define SSL_CTRL_EXTRA_CHAIN_CERT		14
 
 #define SSL_CTRL_SET_MSG_CALLBACK               15
 #define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
 
 /* only applies to datagram connections */
 #define SSL_CTRL_SET_MTU                17
 /* Stats */
 #define SSL_CTRL_SESS_NUMBER			20
 #define SSL_CTRL_SESS_CONNECT			21
 #define SSL_CTRL_SESS_CONNECT_GOOD		22
 #define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23
 #define SSL_CTRL_SESS_ACCEPT			24
 #define SSL_CTRL_SESS_ACCEPT_GOOD		25
 #define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26
 #define SSL_CTRL_SESS_HIT			27
 #define SSL_CTRL_SESS_CB_HIT			28
 #define SSL_CTRL_SESS_MISSES			29
 #define SSL_CTRL_SESS_TIMEOUTS			30
 #define SSL_CTRL_SESS_CACHE_FULL		31
 #define SSL_CTRL_OPTIONS			32
 #define SSL_CTRL_MODE				33
 
 #define SSL_CTRL_GET_READ_AHEAD			40
 #define SSL_CTRL_SET_READ_AHEAD			41
 #define SSL_CTRL_SET_SESS_CACHE_SIZE		42
 #define SSL_CTRL_GET_SESS_CACHE_SIZE		43
 #define SSL_CTRL_SET_SESS_CACHE_MODE		44
 #define SSL_CTRL_GET_SESS_CACHE_MODE		45
 
 #define SSL_CTRL_GET_MAX_CERT_LIST		50
 #define SSL_CTRL_SET_MAX_CERT_LIST		51
 
 /* see tls1.h for macros based on these */
 #ifndef OPENSSL_NO_TLSEXT
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB	53
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG	54
 #define SSL_CTRL_SET_TLSEXT_HOSTNAME		55
 #define SSL_CTRL_SET_TLSEXT_DEBUG_CB		56
 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57
 #define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59
 
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71
 
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72
 #endif
 
 #define DTLS_CTRL_GET_TIMEOUT		73
 #define DTLS_CTRL_HANDLE_TIMEOUT	74
 #define DTLS_CTRL_LISTEN			75
 
 #define SSL_CTRL_GET_RI_SUPPORT			76
 #define SSL_CTRL_CLEAR_OPTIONS			77
 #define SSL_CTRL_CLEAR_MODE			78
 
 #define SSL_CTRL_CHECK_PROTO_VERSION		119
 
 #define DTLSv1_get_timeout(ssl, arg) \
 	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
 #define DTLSv1_handle_timeout(ssl) \
 	SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
 #define DTLSv1_listen(ssl, peer) \
 	SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
 
 #define SSL_session_reused(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
 #define SSL_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_clear_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_total_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
 
 #define SSL_CTX_need_tmp_RSA(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_CTX_set_tmp_rsa(ctx,rsa) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_CTX_set_tmp_dh(ctx,dh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_need_tmp_RSA(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_set_tmp_rsa(ssl,rsa) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_set_tmp_dh(ssl,dh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_set_tmp_ecdh(ssl,ecdh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_CTX_add_extra_chain_cert(ctx,x509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
 
 #ifndef OPENSSL_NO_BIO
 BIO_METHOD *BIO_f_ssl(void);
 BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
 BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
 BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
 int BIO_ssl_copy_session_id(BIO *to,BIO *from);
 void BIO_ssl_shutdown(BIO *ssl_bio);
 
 #endif
 
 int	SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
 SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
 void	SSL_CTX_free(SSL_CTX *);
 long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
 long SSL_CTX_get_timeout(const SSL_CTX *ctx);
 X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
 void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
 int SSL_want(const SSL *s);
 int	SSL_clear(SSL *s);
 
 void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
 
 SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
 int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
 char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
 const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
 
 int	SSL_get_fd(const SSL *s);
 int	SSL_get_rfd(const SSL *s);
 int	SSL_get_wfd(const SSL *s);
 const char  * SSL_get_cipher_list(const SSL *s,int n);
 char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
 int	SSL_get_read_ahead(const SSL * s);
 int	SSL_pending(const SSL *s);
 #ifndef OPENSSL_NO_SOCK
 int	SSL_set_fd(SSL *s, int fd);
 int	SSL_set_rfd(SSL *s, int fd);
 int	SSL_set_wfd(SSL *s, int fd);
 #endif
 #ifndef OPENSSL_NO_BIO
 void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
 BIO *	SSL_get_rbio(const SSL *s);
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
 int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
 void	SSL_set_verify(SSL *s, int mode,
 		       int (*callback)(int ok,X509_STORE_CTX *ctx));
 void	SSL_set_verify_depth(SSL *s, int depth);
 #ifndef OPENSSL_NO_RSA
 int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
 #endif
 int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
 int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
 
 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_certificate_file(SSL *ssl, const char *file, int type);
 int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
 STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
 int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					    const char *file);
 #ifndef OPENSSL_SYS_VMS
 #ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
 int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					   const char *dir);
 #endif
 #endif
 
 #endif
 
 void	SSL_load_error_strings(void );
 const char *SSL_state_string(const SSL *s);
 const char *SSL_rstate_string(const SSL *s);
 const char *SSL_state_string_long(const SSL *s);
 const char *SSL_rstate_string_long(const SSL *s);
 long	SSL_SESSION_get_time(const SSL_SESSION *s);
 long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
 long	SSL_SESSION_get_timeout(const SSL_SESSION *s);
 long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
 void	SSL_copy_session_id(SSL *to,const SSL *from);
 
 SSL_SESSION *SSL_SESSION_new(void);
 unsigned long SSL_SESSION_hash(const SSL_SESSION *a);
 int	SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len);
 #ifndef OPENSSL_NO_FP_API
 int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
 #endif
 #ifndef OPENSSL_NO_BIO
 int	SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
 #endif
 void	SSL_SESSION_free(SSL_SESSION *ses);
 int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
 int	SSL_set_session(SSL *to, SSL_SESSION *session);
 int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
 int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
 int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
 int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
 int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
 					unsigned int id_len);
 SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
 			     long length);
 
 #ifdef HEADER_X509_H
 X509 *	SSL_get_peer_certificate(const SSL *s);
 #endif
 
 STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
 
 int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
 int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
 int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
 void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
 			int (*callback)(int, X509_STORE_CTX *));
 void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
 void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
 #ifndef OPENSSL_NO_RSA
 int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
 #endif
 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
 int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
 	const unsigned char *d, long len);
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
 
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
 
 int SSL_CTX_check_private_key(const SSL_CTX *ctx);
 int SSL_check_private_key(const SSL *ctx);
 
 int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
 				       unsigned int sid_ctx_len);
 
 SSL *	SSL_new(SSL_CTX *ctx);
 int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
 				   unsigned int sid_ctx_len);
 
 int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
 int SSL_set_purpose(SSL *s, int purpose);
 int SSL_CTX_set_trust(SSL_CTX *s, int trust);
 int SSL_set_trust(SSL *s, int trust);
 
 void	SSL_free(SSL *ssl);
 int 	SSL_accept(SSL *ssl);
 int 	SSL_connect(SSL *ssl);
 int 	SSL_read(SSL *ssl,void *buf,int num);
 int 	SSL_peek(SSL *ssl,void *buf,int num);
 int 	SSL_write(SSL *ssl,const void *buf,int num);
 long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
 long	SSL_callback_ctrl(SSL *, int, void (*)(void));
 long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
 long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
 
 int	SSL_get_error(const SSL *s,int ret_code);
 const char *SSL_get_version(const SSL *s);
 
 /* This sets the 'default' SSL version that SSL_new() will create */
 int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
 
 SSL_METHOD *SSLv2_method(void);		/* SSLv2 */
 SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */
 SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
 
 SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
 SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
 SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
 
 SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */
 SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */
 SSL_METHOD *SSLv23_client_method(void);	/* SSLv3 but can rollback to v2 */
 
 SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
 SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
 SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
 
 SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */
 SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */
 SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */
 
 STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
 
 int SSL_do_handshake(SSL *s);
 int SSL_renegotiate(SSL *s);
 int SSL_renegotiate_pending(SSL *s);
 int SSL_shutdown(SSL *s);
 
 SSL_METHOD *SSL_get_ssl_method(SSL *s);
 int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
 const char *SSL_alert_type_string_long(int value);
 const char *SSL_alert_type_string(int value);
 const char *SSL_alert_desc_string_long(int value);
 const char *SSL_alert_desc_string(int value);
 
 void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
 void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
 STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
 STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
 int SSL_add_client_CA(SSL *ssl,X509 *x);
 int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
 
 void SSL_set_connect_state(SSL *s);
 void SSL_set_accept_state(SSL *s);
 
 long SSL_get_default_timeout(const SSL *s);
 
 int SSL_library_init(void );
 
 char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
 STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
 
 SSL *SSL_dup(SSL *ssl);
 
 X509 *SSL_get_certificate(const SSL *ssl);
 /* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
 
 void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
 int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
 void SSL_set_quiet_shutdown(SSL *ssl,int mode);
 int SSL_get_quiet_shutdown(const SSL *ssl);
 void SSL_set_shutdown(SSL *ssl,int mode);
 int SSL_get_shutdown(const SSL *ssl);
 int SSL_version(const SSL *ssl);
 int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
 int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
 	const char *CApath);
 #define SSL_get0_session SSL_get_session /* just peek at pointer */
 SSL_SESSION *SSL_get_session(const SSL *ssl);
 SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
 SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
 SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
 void SSL_set_info_callback(SSL *ssl,
 			   void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
 int SSL_state(const SSL *ssl);
 
 void SSL_set_verify_result(SSL *ssl,long v);
 long SSL_get_verify_result(const SSL *ssl);
 
 int SSL_set_ex_data(SSL *ssl,int idx,void *data);
 void *SSL_get_ex_data(const SSL *ssl,int idx);
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
 void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
 int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_get_ex_data_X509_STORE_CTX_idx(void );
 
 #define SSL_CTX_sess_set_cache_size(ctx,t) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
 #define SSL_CTX_sess_get_cache_size(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
 #define SSL_CTX_set_session_cache_mode(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
 #define SSL_CTX_get_session_cache_mode(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
 
 #define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
 #define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
 #define SSL_CTX_get_read_ahead(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
 #define SSL_CTX_set_read_ahead(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
 #define SSL_CTX_get_max_cert_list(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_CTX_set_max_cert_list(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 #define SSL_get_max_cert_list(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_set_max_cert_list(ssl,m) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 
      /* NB: the keylength is only applicable when is_export is true */
 #ifndef OPENSSL_NO_RSA
 void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 
 void SSL_set_tmp_rsa_callback(SSL *ssl,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 #endif
 #ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_dh_callback(SSL *ssl,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 #ifndef OPENSSL_NO_ECDH
 void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_ecdh_callback(SSL *ssl,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 
 #ifndef OPENSSL_NO_COMP
 const COMP_METHOD *SSL_get_current_compression(SSL *s);
 const COMP_METHOD *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const COMP_METHOD *comp);
 STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
 #else
 const void *SSL_get_current_compression(SSL *s);
 const void *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const void *comp);
 void *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,void *cm);
 #endif
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
 void ERR_load_SSL_strings(void);
 
 /* Error codes for the SSL functions. */
 
 /* Function codes. */
 #define SSL_F_CLIENT_CERTIFICATE			 100
 #define SSL_F_CLIENT_FINISHED				 167
 #define SSL_F_CLIENT_HELLO				 101
 #define SSL_F_CLIENT_MASTER_KEY				 102
 #define SSL_F_D2I_SSL_SESSION				 103
 #define SSL_F_DO_DTLS1_WRITE				 245
 #define SSL_F_DO_SSL3_WRITE				 104
 #define SSL_F_DTLS1_ACCEPT				 246
 #define SSL_F_DTLS1_ADD_CERT_TO_BUF			 280
 #define SSL_F_DTLS1_BUFFER_RECORD			 247
 #define SSL_F_DTLS1_CHECK_TIMEOUT_NUM			 293
 #define SSL_F_DTLS1_CLIENT_HELLO			 248
 #define SSL_F_DTLS1_CONNECT				 249
 #define SSL_F_DTLS1_ENC					 250
 #define SSL_F_DTLS1_GET_HELLO_VERIFY			 251
 #define SSL_F_DTLS1_GET_MESSAGE				 252
 #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
 #define SSL_F_DTLS1_GET_RECORD				 254
 #define SSL_F_DTLS1_HANDLE_TIMEOUT			 282
 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
 #define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 277
 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
 #define SSL_F_DTLS1_PROCESS_RECORD			 257
 #define SSL_F_DTLS1_READ_BYTES				 258
 #define SSL_F_DTLS1_READ_FAILED				 259
 #define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260
 #define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261
 #define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262
 #define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263
 #define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264
 #define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265
 #define SSL_F_DTLS1_SEND_SERVER_HELLO			 266
 #define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267
 #define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268
 #define SSL_F_GET_CLIENT_FINISHED			 105
 #define SSL_F_GET_CLIENT_HELLO				 106
 #define SSL_F_GET_CLIENT_MASTER_KEY			 107
 #define SSL_F_GET_SERVER_FINISHED			 108
 #define SSL_F_GET_SERVER_HELLO				 109
 #define SSL_F_GET_SERVER_VERIFY				 110
 #define SSL_F_I2D_SSL_SESSION				 111
 #define SSL_F_READ_N					 112
 #define SSL_F_REQUEST_CERTIFICATE			 113
 #define SSL_F_SERVER_FINISH				 239
 #define SSL_F_SERVER_HELLO				 114
 #define SSL_F_SERVER_VERIFY				 240
 #define SSL_F_SSL23_ACCEPT				 115
 #define SSL_F_SSL23_CLIENT_HELLO			 116
 #define SSL_F_SSL23_CONNECT				 117
 #define SSL_F_SSL23_GET_CLIENT_HELLO			 118
 #define SSL_F_SSL23_GET_SERVER_HELLO			 119
 #define SSL_F_SSL23_PEEK				 237
 #define SSL_F_SSL23_READ				 120
 #define SSL_F_SSL23_WRITE				 121
 #define SSL_F_SSL2_ACCEPT				 122
 #define SSL_F_SSL2_CONNECT				 123
 #define SSL_F_SSL2_ENC_INIT				 124
 #define SSL_F_SSL2_GENERATE_KEY_MATERIAL		 241
 #define SSL_F_SSL2_PEEK					 234
 #define SSL_F_SSL2_READ					 125
 #define SSL_F_SSL2_READ_INTERNAL			 236
 #define SSL_F_SSL2_SET_CERTIFICATE			 126
 #define SSL_F_SSL2_WRITE				 127
 #define SSL_F_SSL3_ACCEPT				 128
 #define SSL_F_SSL3_ADD_CERT_TO_BUF			 281
 #define SSL_F_SSL3_CALLBACK_CTRL			 233
 #define SSL_F_SSL3_CHANGE_CIPHER_STATE			 129
 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM		 130
 #define SSL_F_SSL3_CHECK_CLIENT_HELLO			 292
 #define SSL_F_SSL3_CLIENT_HELLO				 131
 #define SSL_F_SSL3_CONNECT				 132
 #define SSL_F_SSL3_CTRL					 213
 #define SSL_F_SSL3_CTX_CTRL				 133
 #define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 279
 #define SSL_F_SSL3_ENC					 134
 #define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
 #define SSL_F_SSL3_GET_CERT_STATUS			 288
 #define SSL_F_SSL3_GET_CERT_VERIFY			 136
 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
 #define SSL_F_SSL3_GET_CLIENT_HELLO			 138
 #define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE		 139
 #define SSL_F_SSL3_GET_FINISHED				 140
 #define SSL_F_SSL3_GET_KEY_EXCHANGE			 141
 #define SSL_F_SSL3_GET_MESSAGE				 142
 #define SSL_F_SSL3_GET_NEW_SESSION_TICKET		 283
 #define SSL_F_SSL3_GET_RECORD				 143
 #define SSL_F_SSL3_GET_SERVER_CERTIFICATE		 144
 #define SSL_F_SSL3_GET_SERVER_DONE			 145
 #define SSL_F_SSL3_GET_SERVER_HELLO			 146
 #define SSL_F_SSL3_NEW_SESSION_TICKET			 284
 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147
 #define SSL_F_SSL3_PEEK					 235
 #define SSL_F_SSL3_READ_BYTES				 148
 #define SSL_F_SSL3_READ_N				 149
 #define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST		 150
 #define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE		 151
 #define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE		 152
 #define SSL_F_SSL3_SEND_CLIENT_VERIFY			 153
 #define SSL_F_SSL3_SEND_SERVER_CERTIFICATE		 154
 #define SSL_F_SSL3_SEND_SERVER_HELLO			 242
 #define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155
 #define SSL_F_SSL3_SETUP_BUFFERS			 156
 #define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
 #define SSL_F_SSL3_WRITE_BYTES				 158
 #define SSL_F_SSL3_WRITE_PENDING			 159
 #define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 285
 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 272
 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215
 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216
 #define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT	 286
 #define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 273
 #define SSL_F_SSL_BAD_METHOD				 160
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
 #define SSL_F_SSL_CERT_DUP				 221
 #define SSL_F_SSL_CERT_INST				 222
 #define SSL_F_SSL_CERT_INSTANTIATE			 214
 #define SSL_F_SSL_CERT_NEW				 162
 #define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
 #define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 274
 #define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230
 #define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231
 #define SSL_F_SSL_CLEAR					 164
 #define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165
 #define SSL_F_SSL_CREATE_CIPHER_LIST			 166
 #define SSL_F_SSL_CTRL					 232
 #define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
 #define SSL_F_SSL_CTX_NEW				 169
 #define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
 #define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 278
 #define SSL_F_SSL_CTX_SET_PURPOSE			 226
 #define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
 #define SSL_F_SSL_CTX_SET_TRUST				 229
 #define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
 #define SSL_F_SSL_DO_HANDSHAKE				 180
 #define SSL_F_SSL_GET_NEW_SESSION			 181
 #define SSL_F_SSL_GET_PREV_SESSION			 217
 #define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
 #define SSL_F_SSL_GET_SERVER_SEND_PKEY			 317
 #define SSL_F_SSL_GET_SIGN_PKEY				 183
 #define SSL_F_SSL_INIT_WBIO_BUFFER			 184
 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
 #define SSL_F_SSL_NEW					 186
 #define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 287
 #define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 290
 #define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 289
 #define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 291
 #define SSL_F_SSL_PEEK					 270
 #define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 275
 #define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 276
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESS_CERT_NEW				 225
 #define SSL_F_SSL_SET_CERT				 191
 #define SSL_F_SSL_SET_CIPHER_LIST			 271
 #define SSL_F_SSL_SET_FD				 192
 #define SSL_F_SSL_SET_PKEY				 193
 #define SSL_F_SSL_SET_PURPOSE				 227
 #define SSL_F_SSL_SET_RFD				 194
 #define SSL_F_SSL_SET_SESSION				 195
 #define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
 #define SSL_F_SSL_SET_TRUST				 228
 #define SSL_F_SSL_SET_WFD				 196
 #define SSL_F_SSL_SHUTDOWN				 224
 #define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
 #define SSL_F_SSL_UNDEFINED_FUNCTION			 197
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
 #define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
 #define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
 #define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
 #define SSL_F_SSL_WRITE					 208
 #define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
 #define SSL_F_TLS1_ENC					 210
 #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
 #define SSL_F_WRITE_PENDING				 212
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
 #define SSL_R_BAD_ALERT_RECORD				 101
 #define SSL_R_BAD_AUTHENTICATION_TYPE			 102
 #define SSL_R_BAD_CHANGE_CIPHER_SPEC			 103
 #define SSL_R_BAD_CHECKSUM				 104
 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK		 106
 #define SSL_R_BAD_DECOMPRESSION				 107
 #define SSL_R_BAD_DH_G_LENGTH				 108
 #define SSL_R_BAD_DH_PUB_KEY_LENGTH			 109
 #define SSL_R_BAD_DH_P_LENGTH				 110
 #define SSL_R_BAD_DIGEST_LENGTH				 111
 #define SSL_R_BAD_DSA_SIGNATURE				 112
 #define SSL_R_BAD_ECC_CERT				 304
 #define SSL_R_BAD_ECDSA_SIGNATURE			 305
 #define SSL_R_BAD_ECPOINT				 306
 #define SSL_R_BAD_HELLO_REQUEST				 105
 #define SSL_R_BAD_LENGTH				 271
 #define SSL_R_BAD_MAC_DECODE				 113
 #define SSL_R_BAD_MESSAGE_TYPE				 114
 #define SSL_R_BAD_PACKET_LENGTH				 115
 #define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116
 #define SSL_R_BAD_RESPONSE_ARGUMENT			 117
 #define SSL_R_BAD_RSA_DECRYPT				 118
 #define SSL_R_BAD_RSA_ENCRYPT				 119
 #define SSL_R_BAD_RSA_E_LENGTH				 120
 #define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
 #define SSL_R_BAD_RSA_SIGNATURE				 122
 #define SSL_R_BAD_SIGNATURE				 123
 #define SSL_R_BAD_SSL_FILETYPE				 124
 #define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
 #define SSL_R_BAD_STATE					 126
 #define SSL_R_BAD_WRITE_RETRY				 127
 #define SSL_R_BIO_NOT_SET				 128
 #define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
 #define SSL_R_BN_LIB					 130
 #define SSL_R_CA_DN_LENGTH_MISMATCH			 131
 #define SSL_R_CA_DN_TOO_LONG				 132
 #define SSL_R_CCS_RECEIVED_EARLY			 133
 #define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
 #define SSL_R_CERT_LENGTH_MISMATCH			 135
 #define SSL_R_CHALLENGE_IS_DIFFERENT			 136
 #define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
 #define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
 #define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
 #define SSL_R_CLIENTHELLO_TLSEXT			 157
 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
 #define SSL_R_COMPRESSION_FAILURE			 141
 #define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307
 #define SSL_R_COMPRESSION_LIBRARY_ERROR			 142
 #define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143
 #define SSL_R_CONNECTION_TYPE_NOT_SET			 144
 #define SSL_R_COOKIE_MISMATCH				 308
 #define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145
 #define SSL_R_DATA_LENGTH_TOO_LONG			 146
 #define SSL_R_DECRYPTION_FAILED				 147
 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281
 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148
 #define SSL_R_DIGEST_CHECK_FAILED			 149
 #define SSL_R_DTLS_MESSAGE_TOO_BIG			 318
 #define SSL_R_DUPLICATE_COMPRESSION_ID			 309
 #define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310
 #define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150
 #define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282
 #define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151
 #define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152
 #define SSL_R_EXTRA_DATA_IN_MESSAGE			 153
 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154
 #define SSL_R_HTTPS_PROXY_REQUEST			 155
 #define SSL_R_HTTP_REQUEST				 156
 #define SSL_R_ILLEGAL_PADDING				 283
 #define SSL_R_INAPPROPRIATE_FALLBACK			 373
 #define SSL_R_INVALID_CHALLENGE_LENGTH			 158
 #define SSL_R_INVALID_COMMAND				 280
 #define SSL_R_INVALID_PURPOSE				 278
 #define SSL_R_INVALID_STATUS_RESPONSE			 316
 #define SSL_R_INVALID_TICKET_KEYS_LENGTH		 275
 #define SSL_R_INVALID_TRUST				 279
 #define SSL_R_KEY_ARG_TOO_LONG				 284
 #define SSL_R_KRB5					 285
 #define SSL_R_KRB5_C_CC_PRINC				 286
 #define SSL_R_KRB5_C_GET_CRED				 287
 #define SSL_R_KRB5_C_INIT				 288
 #define SSL_R_KRB5_C_MK_REQ				 289
 #define SSL_R_KRB5_S_BAD_TICKET				 290
 #define SSL_R_KRB5_S_INIT				 291
 #define SSL_R_KRB5_S_RD_REQ				 292
 #define SSL_R_KRB5_S_TKT_EXPIRED			 293
 #define SSL_R_KRB5_S_TKT_NYV				 294
 #define SSL_R_KRB5_S_TKT_SKEW				 295
 #define SSL_R_LENGTH_MISMATCH				 159
 #define SSL_R_LENGTH_TOO_SHORT				 160
 #define SSL_R_LIBRARY_BUG				 274
 #define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161
 #define SSL_R_MESSAGE_TOO_LONG				 296
 #define SSL_R_MISSING_DH_DSA_CERT			 162
 #define SSL_R_MISSING_DH_KEY				 163
 #define SSL_R_MISSING_DH_RSA_CERT			 164
 #define SSL_R_MISSING_DSA_SIGNING_CERT			 165
 #define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166
 #define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167
 #define SSL_R_MISSING_RSA_CERTIFICATE			 168
 #define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169
 #define SSL_R_MISSING_RSA_SIGNING_CERT			 170
 #define SSL_R_MISSING_TMP_DH_KEY			 171
 #define SSL_R_MISSING_TMP_ECDH_KEY			 311
 #define SSL_R_MISSING_TMP_RSA_KEY			 172
 #define SSL_R_MISSING_TMP_RSA_PKEY			 173
 #define SSL_R_MISSING_VERIFY_MESSAGE			 174
 #define SSL_R_MULTIPLE_SGC_RESTARTS			 325
 #define SSL_R_NON_SSLV2_INITIAL_PACKET			 175
 #define SSL_R_NO_CERTIFICATES_RETURNED			 176
 #define SSL_R_NO_CERTIFICATE_ASSIGNED			 177
 #define SSL_R_NO_CERTIFICATE_RETURNED			 178
 #define SSL_R_NO_CERTIFICATE_SET			 179
 #define SSL_R_NO_CERTIFICATE_SPECIFIED			 180
 #define SSL_R_NO_CIPHERS_AVAILABLE			 181
 #define SSL_R_NO_CIPHERS_PASSED				 182
 #define SSL_R_NO_CIPHERS_SPECIFIED			 183
 #define SSL_R_NO_CIPHER_LIST				 184
 #define SSL_R_NO_CIPHER_MATCH				 185
 #define SSL_R_NO_CLIENT_CERT_METHOD			 317
 #define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
 #define SSL_R_NO_COMPRESSION_SPECIFIED			 187
 #define SSL_R_NO_METHOD_SPECIFIED			 188
 #define SSL_R_NO_PRIVATEKEY				 189
 #define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
 #define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
 #define SSL_R_NO_PUBLICKEY				 192
 #define SSL_R_NO_RENEGOTIATION				 319
 #define SSL_R_NO_SHARED_CIPHER				 193
 #define SSL_R_NO_VERIFY_CALLBACK			 194
 #define SSL_R_NULL_SSL_CTX				 195
 #define SSL_R_NULL_SSL_METHOD_PASSED			 196
 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
 #define SSL_R_PACKET_LENGTH_TOO_LONG			 198
 #define SSL_R_PARSE_TLSEXT				 223
 #define SSL_R_PATH_TOO_LONG				 270
 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199
 #define SSL_R_PEER_ERROR				 200
 #define SSL_R_PEER_ERROR_CERTIFICATE			 201
 #define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202
 #define SSL_R_PEER_ERROR_NO_CIPHER			 203
 #define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204
 #define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205
 #define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206
 #define SSL_R_PROTOCOL_IS_SHUTDOWN			 207
 #define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208
 #define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209
 #define SSL_R_PUBLIC_KEY_NOT_RSA			 210
 #define SSL_R_READ_BIO_NOT_SET				 211
 #define SSL_R_READ_TIMEOUT_EXPIRED			 312
 #define SSL_R_READ_WRONG_PACKET_TYPE			 212
 #define SSL_R_RECORD_LENGTH_MISMATCH			 213
 #define SSL_R_RECORD_TOO_LARGE				 214
 #define SSL_R_RECORD_TOO_SMALL				 298
 #define SSL_R_RENEGOTIATE_EXT_TOO_LONG			 320
 #define SSL_R_RENEGOTIATION_ENCODING_ERR		 321
 #define SSL_R_RENEGOTIATION_MISMATCH			 322
 #define SSL_R_REQUIRED_CIPHER_MISSING			 215
 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216
 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217
 #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218
 #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 324
 #define SSL_R_SERVERHELLO_TLSEXT			 224
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
 #define SSL_R_SHORT_READ				 219
 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
 #define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME		 225
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE		 226
 #define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300
 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222
 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE		 1042
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		 1020
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		 1045
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED		 1044
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		 1046
 #define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE		 1030
 #define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		 1040
 #define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		 1047
 #define SSL_R_SSLV3_ALERT_NO_CERTIFICATE		 1041
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
 #define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
 #define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228
 #define SSL_R_SSL_HANDSHAKE_FAILURE			 229
 #define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230
 #define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301
 #define SSL_R_SSL_SESSION_ID_CONFLICT			 302
 #define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273
 #define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303
 #define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231
 #define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049
 #define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050
 #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021
 #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051
 #define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060
 #define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK	 1086
 #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071
 #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080
 #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100
 #define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070
 #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022
 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048
 #define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE		 1114
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE	 1113
 #define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE		 1111
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112
 #define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 227
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
 #define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
 #define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
 #define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237
 #define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238
 #define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314
 #define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239
 #define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240
 #define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241
 #define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242
 #define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243
 #define SSL_R_UNEXPECTED_MESSAGE			 244
 #define SSL_R_UNEXPECTED_RECORD				 245
 #define SSL_R_UNINITIALIZED				 276
 #define SSL_R_UNKNOWN_ALERT_TYPE			 246
 #define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247
 #define SSL_R_UNKNOWN_CIPHER_RETURNED			 248
 #define SSL_R_UNKNOWN_CIPHER_TYPE			 249
 #define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250
 #define SSL_R_UNKNOWN_PKEY_TYPE				 251
 #define SSL_R_UNKNOWN_PROTOCOL				 252
 #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
 #define SSL_R_UNKNOWN_SSL_VERSION			 254
 #define SSL_R_UNKNOWN_STATE				 255
 #define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 323
 #define SSL_R_UNSUPPORTED_CIPHER			 256
 #define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
 #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
 #define SSL_R_UNSUPPORTED_PROTOCOL			 258
 #define SSL_R_UNSUPPORTED_SSL_VERSION			 259
 #define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
 #define SSL_R_WRITE_BIO_NOT_SET				 260
 #define SSL_R_WRONG_CIPHER_RETURNED			 261
 #define SSL_R_WRONG_MESSAGE_TYPE			 262
 #define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263
 #define SSL_R_WRONG_SIGNATURE_LENGTH			 264
 #define SSL_R_WRONG_SIGNATURE_SIZE			 265
 #define SSL_R_WRONG_SSL_VERSION				 266
 #define SSL_R_WRONG_VERSION_NUMBER			 267
 #define SSL_R_X509_LIB					 268
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
 
 #ifdef  __cplusplus
 }
 #endif
 #endif
Index: releng/8.4/crypto/openssl/ssl/ssl_err.c
===================================================================
--- releng/8.4/crypto/openssl/ssl/ssl_err.c	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/ssl_err.c	(revision 284295)
@@ -1,545 +1,546 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
  * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 /* NOTE: this file was auto generated by the mkerr.pl script: any changes
  * made to it will be overwritten when the script next updates this file,
  * only reason strings will be preserved.
  */
 
 #include 
 #include 
 #include 
 
 /* BEGIN ERROR CODES */
 #ifndef OPENSSL_NO_ERR
 
 #define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0)
 #define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason)
 
 static ERR_STRING_DATA SSL_str_functs[]=
 	{
 {ERR_FUNC(SSL_F_CLIENT_CERTIFICATE),	"CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_CLIENT_FINISHED),	"CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_CLIENT_HELLO),	"CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_CLIENT_MASTER_KEY),	"CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_D2I_SSL_SESSION),	"d2i_SSL_SESSION"},
 {ERR_FUNC(SSL_F_DO_DTLS1_WRITE),	"DO_DTLS1_WRITE"},
 {ERR_FUNC(SSL_F_DO_SSL3_WRITE),	"DO_SSL3_WRITE"},
 {ERR_FUNC(SSL_F_DTLS1_ACCEPT),	"DTLS1_ACCEPT"},
 {ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF),	"DTLS1_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD),	"DTLS1_BUFFER_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM),	"DTLS1_CHECK_TIMEOUT_NUM"},
 {ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO),	"DTLS1_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_CONNECT),	"DTLS1_CONNECT"},
 {ERR_FUNC(SSL_F_DTLS1_ENC),	"DTLS1_ENC"},
 {ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY),	"DTLS1_GET_HELLO_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE),	"DTLS1_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT),	"DTLS1_HANDLE_TIMEOUT"},
 {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"},
 {ERR_FUNC(SSL_F_DTLS1_READ_FAILED),	"DTLS1_READ_FAILED"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST),	"DTLS1_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE),	"DTLS1_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE),	"DTLS1_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY),	"DTLS1_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),	"DTLS1_SEND_HELLO_VERIFY_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE),	"DTLS1_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO),	"DTLS1_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),	"DTLS1_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),	"DTLS1_WRITE_APP_DATA_BYTES"},
 {ERR_FUNC(SSL_F_GET_CLIENT_FINISHED),	"GET_CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_GET_CLIENT_HELLO),	"GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY),	"GET_CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_GET_SERVER_FINISHED),	"GET_SERVER_FINISHED"},
 {ERR_FUNC(SSL_F_GET_SERVER_HELLO),	"GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_GET_SERVER_VERIFY),	"GET_SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_I2D_SSL_SESSION),	"i2d_SSL_SESSION"},
 {ERR_FUNC(SSL_F_READ_N),	"READ_N"},
 {ERR_FUNC(SSL_F_REQUEST_CERTIFICATE),	"REQUEST_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SERVER_FINISH),	"SERVER_FINISH"},
 {ERR_FUNC(SSL_F_SERVER_HELLO),	"SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SERVER_VERIFY),	"SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_SSL23_ACCEPT),	"SSL23_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO),	"SSL23_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_CONNECT),	"SSL23_CONNECT"},
 {ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO),	"SSL23_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO),	"SSL23_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_PEEK),	"SSL23_PEEK"},
 {ERR_FUNC(SSL_F_SSL23_READ),	"SSL23_READ"},
 {ERR_FUNC(SSL_F_SSL23_WRITE),	"SSL23_WRITE"},
 {ERR_FUNC(SSL_F_SSL2_ACCEPT),	"SSL2_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL2_CONNECT),	"SSL2_CONNECT"},
 {ERR_FUNC(SSL_F_SSL2_ENC_INIT),	"SSL2_ENC_INIT"},
 {ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL),	"SSL2_GENERATE_KEY_MATERIAL"},
 {ERR_FUNC(SSL_F_SSL2_PEEK),	"SSL2_PEEK"},
 {ERR_FUNC(SSL_F_SSL2_READ),	"SSL2_READ"},
 {ERR_FUNC(SSL_F_SSL2_READ_INTERNAL),	"SSL2_READ_INTERNAL"},
 {ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE),	"SSL2_SET_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL2_WRITE),	"SSL2_WRITE"},
 {ERR_FUNC(SSL_F_SSL3_ACCEPT),	"SSL3_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF),	"SSL3_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),	"SSL3_CALLBACK_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),	"SSL3_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),	"SSL3_CHECK_CERT_AND_ALGORITHM"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO),	"SSL3_CHECK_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),	"SSL3_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"},
 {ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"},
 {ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"},
 {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS),	"SSL3_GET_CERT_STATUS"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY),	"SSL3_GET_CERT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),	"SSL3_GET_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),	"SSL3_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE),	"SSL3_GET_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_FINISHED),	"SSL3_GET_FINISHED"},
 {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),	"SSL3_GET_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),	"SSL3_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),	"SSL3_GET_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_GET_RECORD),	"SSL3_GET_RECORD"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),	"SSL3_GET_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE),	"SSL3_GET_SERVER_DONE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),	"SSL3_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),	"SSL3_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),	"SSL3_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL3_PEEK),	"SSL3_PEEK"},
 {ERR_FUNC(SSL_F_SSL3_READ_BYTES),	"SSL3_READ_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_READ_N),	"SSL3_READ_N"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST),	"SSL3_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE),	"SSL3_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY),	"SSL3_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE),	"SSL3_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO),	"SSL3_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE),	"SSL3_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_BUFFERS),	"SSL3_SETUP_BUFFERS"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK),	"SSL3_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),	"SSL_add_dir_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),	"SSL_add_file_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"SSL_ADD_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"SSL_BAD_METHOD"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"SSL_BYTES_TO_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CERT_DUP),	"SSL_CERT_DUP"},
 {ERR_FUNC(SSL_F_SSL_CERT_INST),	"SSL_CERT_INST"},
 {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"},
 {ERR_FUNC(SSL_F_SSL_CERT_NEW),	"SSL_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),	"SSL_CIPHER_PROCESS_RULESTR"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),	"SSL_CIPHER_STRENGTH_SORT"},
 {ERR_FUNC(SSL_F_SSL_CLEAR),	"SSL_clear"},
 {ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),	"SSL_COMP_add_compression_method"},
 {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST),	"SSL_CREATE_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
 {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
 {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY),	"SSL_GET_SERVER_SEND_PKEY"},
 {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
 {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
 {ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP),		"ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_SET_CERT),	"SSL_SET_CERT"},
 {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),	"SSL_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_SET_FD),	"SSL_set_fd"},
 {ERR_FUNC(SSL_F_SSL_SET_PKEY),	"SSL_SET_PKEY"},
 {ERR_FUNC(SSL_F_SSL_SET_PURPOSE),	"SSL_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_SET_RFD),	"SSL_set_rfd"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION),	"SSL_set_session"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),	"SSL_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_SET_TRUST),	"SSL_set_trust"},
 {ERR_FUNC(SSL_F_SSL_SET_WFD),	"SSL_set_wfd"},
 {ERR_FUNC(SSL_F_SSL_SHUTDOWN),	"SSL_shutdown"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION),	"SSL_UNDEFINED_CONST_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION),	"SSL_UNDEFINED_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),	"SSL_UNDEFINED_VOID_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE),	"SSL_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1),	"SSL_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE),	"SSL_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),	"SSL_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),	"SSL_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),	"SSL_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),	"SSL_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),	"SSL_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"SSL_VERIFY_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"},
 {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
 {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
 {0,NULL}
 	};
 
 static ERR_STRING_DATA SSL_str_reasons[]=
 	{
 {ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"},
 {ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"},
 {ERR_REASON(SSL_R_BAD_ALERT_RECORD)      ,"bad alert record"},
 {ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"},
 {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"},
 {ERR_REASON(SSL_R_BAD_CHECKSUM)          ,"bad checksum"},
 {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),"bad data returned by callback"},
 {ERR_REASON(SSL_R_BAD_DECOMPRESSION)     ,"bad decompression"},
 {ERR_REASON(SSL_R_BAD_DH_G_LENGTH)       ,"bad dh g length"},
 {ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) ,"bad dh pub key length"},
 {ERR_REASON(SSL_R_BAD_DH_P_LENGTH)       ,"bad dh p length"},
 {ERR_REASON(SSL_R_BAD_DIGEST_LENGTH)     ,"bad digest length"},
 {ERR_REASON(SSL_R_BAD_DSA_SIGNATURE)     ,"bad dsa signature"},
 {ERR_REASON(SSL_R_BAD_ECC_CERT)          ,"bad ecc cert"},
 {ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE)   ,"bad ecdsa signature"},
 {ERR_REASON(SSL_R_BAD_ECPOINT)           ,"bad ecpoint"},
 {ERR_REASON(SSL_R_BAD_HELLO_REQUEST)     ,"bad hello request"},
 {ERR_REASON(SSL_R_BAD_LENGTH)            ,"bad length"},
 {ERR_REASON(SSL_R_BAD_MAC_DECODE)        ,"bad mac decode"},
 {ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"},
 {ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"},
 {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"},
 {ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"},
 {ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_E_LENGTH)      ,"bad rsa e length"},
 {ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH),"bad rsa modulus length"},
 {ERR_REASON(SSL_R_BAD_RSA_SIGNATURE)     ,"bad rsa signature"},
 {ERR_REASON(SSL_R_BAD_SIGNATURE)         ,"bad signature"},
 {ERR_REASON(SSL_R_BAD_SSL_FILETYPE)      ,"bad ssl filetype"},
 {ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH),"bad ssl session id length"},
 {ERR_REASON(SSL_R_BAD_STATE)             ,"bad state"},
 {ERR_REASON(SSL_R_BAD_WRITE_RETRY)       ,"bad write retry"},
 {ERR_REASON(SSL_R_BIO_NOT_SET)           ,"bio not set"},
 {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),"block cipher pad is wrong"},
 {ERR_REASON(SSL_R_BN_LIB)                ,"bn lib"},
 {ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) ,"ca dn length mismatch"},
 {ERR_REASON(SSL_R_CA_DN_TOO_LONG)        ,"ca dn too long"},
 {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY)    ,"ccs received early"},
 {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"},
 {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH)  ,"cert length mismatch"},
 {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"},
 {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
 {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
 {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
 {ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"},
 {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
 {ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"},
 {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
 {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),"compression library error"},
 {ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT),"connection id is different"},
 {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET),"connection type not set"},
 {ERR_REASON(SSL_R_COOKIE_MISMATCH)       ,"cookie mismatch"},
 {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),"data between ccs and finished"},
 {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG)  ,"data length too long"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED)     ,"decryption failed"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"},
 {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"},
 {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED)   ,"digest check failed"},
 {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG)  ,"dtls message too big"},
 {ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID),"duplicate compression id"},
 {ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER),"ecgroup too large for cipher"},
 {ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),"encrypted length too long"},
 {ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY),"error generating tmp rsa key"},
 {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),"error in received cipher list"},
 {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"},
 {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"},
 {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"},
 {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"},
 {ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"},
 {ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"},
 {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK),"inappropriate fallback"},
 {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
 {ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"},
 {ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"},
 {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"},
 {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"},
 {ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"},
 {ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"},
 {ERR_REASON(SSL_R_KRB5)                  ,"krb5"},
 {ERR_REASON(SSL_R_KRB5_C_CC_PRINC)       ,"krb5 client cc principal (no tkt?)"},
 {ERR_REASON(SSL_R_KRB5_C_GET_CRED)       ,"krb5 client get cred"},
 {ERR_REASON(SSL_R_KRB5_C_INIT)           ,"krb5 client init"},
 {ERR_REASON(SSL_R_KRB5_C_MK_REQ)         ,"krb5 client mk_req (expired tkt?)"},
 {ERR_REASON(SSL_R_KRB5_S_BAD_TICKET)     ,"krb5 server bad ticket"},
 {ERR_REASON(SSL_R_KRB5_S_INIT)           ,"krb5 server init"},
 {ERR_REASON(SSL_R_KRB5_S_RD_REQ)         ,"krb5 server rd_req (keytab perms?)"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED)    ,"krb5 server tkt expired"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_NYV)        ,"krb5 server tkt not yet valid"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_SKEW)       ,"krb5 server tkt skew"},
 {ERR_REASON(SSL_R_LENGTH_MISMATCH)       ,"length mismatch"},
 {ERR_REASON(SSL_R_LENGTH_TOO_SHORT)      ,"length too short"},
 {ERR_REASON(SSL_R_LIBRARY_BUG)           ,"library bug"},
 {ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS),"library has no ciphers"},
 {ERR_REASON(SSL_R_MESSAGE_TOO_LONG)      ,"message too long"},
 {ERR_REASON(SSL_R_MISSING_DH_DSA_CERT)   ,"missing dh dsa cert"},
 {ERR_REASON(SSL_R_MISSING_DH_KEY)        ,"missing dh key"},
 {ERR_REASON(SSL_R_MISSING_DH_RSA_CERT)   ,"missing dh rsa cert"},
 {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT),"missing dsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY),"missing export tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY),"missing export tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE),"missing rsa certificate"},
 {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),"missing rsa encrypting cert"},
 {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT),"missing rsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY)    ,"missing tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY)  ,"missing tmp ecdh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"},
 {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
 {ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"},
 {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
 {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED),"no certificate returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SET)    ,"no certificate set"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED),"no certificate specified"},
 {ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE)  ,"no ciphers available"},
 {ERR_REASON(SSL_R_NO_CIPHERS_PASSED)     ,"no ciphers passed"},
 {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"},
 {ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"},
 {ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"},
 {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"},
 {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"},
 {ERR_REASON(SSL_R_NO_PRIVATEKEY)         ,"no privatekey"},
 {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"},
 {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"},
 {ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"},
 {ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
 {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
 {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
 {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
 {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
 {ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"},
 {ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"},
 {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"},
 {ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE),"peer error certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE),"peer error no certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER)  ,"peer error no cipher"},
 {ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE),"peer error unsupported certificate type"},
 {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"},
 {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"},
 {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
 {ERR_REASON(SSL_R_READ_BIO_NOT_SET)      ,"read bio not set"},
 {ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED)  ,"read timeout expired"},
 {ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE),"read wrong packet type"},
 {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"},
 {ERR_REASON(SSL_R_RECORD_TOO_LARGE)      ,"record too large"},
 {ERR_REASON(SSL_R_RECORD_TOO_SMALL)      ,"record too small"},
 {ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"},
 {ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"},
 {ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"},
 {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"},
 {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
 {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
 {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
 {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
 {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
 {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
 {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
 {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
 {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
 {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),"sslv3 alert bad record mac"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),"sslv3 alert certificate expired"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),"sslv3 alert certificate revoked"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),"sslv3 alert certificate unknown"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),"sslv3 alert decompression failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),"sslv3 alert handshake failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),"sslv3 alert illegal parameter"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),"sslv3 alert no certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),"sslv3 alert unexpected message"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),"sslv3 alert unsupported certificate"},
 {ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),"ssl ctx has no default ssl version"},
 {ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) ,"ssl handshake failure"},
 {ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),"ssl library has no ciphers"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),"ssl session id callback failed"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT),"ssl session id conflict"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),"ssl session id context too long"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),"ssl session id has bad length"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT),"ssl session id is different"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),"tlsv1 alert access denied"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR),"tlsv1 alert decode error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),"tlsv1 alert inappropriate fallback"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),"tlsv1 alert protocol version"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"},
 {ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"},
 {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
 {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
 {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
 {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
 {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY),"unable to extract public key"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS),"unable to find dh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),"unable to find ecdh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),"unable to find public key parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD),"unable to find ssl method"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES),"unable to load ssl2 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),"unable to load ssl3 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),"unable to load ssl3 sha1 routines"},
 {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE)    ,"unexpected message"},
 {ERR_REASON(SSL_R_UNEXPECTED_RECORD)     ,"unexpected record"},
 {ERR_REASON(SSL_R_UNINITIALIZED)         ,"uninitialized"},
 {ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE)    ,"unknown alert type"},
 {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"},
 {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"},
 {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"},
 {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"},
 {ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"},
 {ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION)   ,"unknown ssl version"},
 {ERR_REASON(SSL_R_UNKNOWN_STATE)         ,"unknown state"},
 {ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"},
 {ERR_REASON(SSL_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
 {ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
 {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"},
 {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"},
 {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"},
 {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
 {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
 {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
 {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
 {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"},
 {ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"},
 {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
 {ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
 {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
 {0,NULL}
 	};
 
 #endif
 
 void ERR_load_SSL_strings(void)
 	{
 #ifndef OPENSSL_NO_ERR
 
 	if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
 		{
 		ERR_load_strings(0,SSL_str_functs);
 		ERR_load_strings(0,SSL_str_reasons);
 		}
 #endif
 	}
Index: releng/8.4/crypto/openssl/ssl/ssl_locl.h
===================================================================
--- releng/8.4/crypto/openssl/ssl/ssl_locl.h	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/ssl_locl.h	(revision 284295)
@@ -1,1044 +1,1045 @@
 /* ssl/ssl_locl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #ifndef HEADER_SSL_LOCL_H
 #define HEADER_SSL_LOCL_H
 #include 
 #include 
 #include 
 #include 
 
 #include "e_os.h"
 
 #include 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #include 
 #include 
 #ifndef OPENSSL_NO_RSA
 #include 
 #endif
 #ifndef OPENSSL_NO_DSA
 #include 
 #endif
 #include 
 #include 
 #include 
 
 #ifdef OPENSSL_BUILD_SHLIBSSL
 # undef OPENSSL_EXTERN
 # define OPENSSL_EXTERN OPENSSL_EXPORT
 #endif
 
 #define PKCS1_CHECK
 
 #define c2l(c,l)	(l = ((unsigned long)(*((c)++)))     , \
 			 l|=(((unsigned long)(*((c)++)))<< 8), \
 			 l|=(((unsigned long)(*((c)++)))<<16), \
 			 l|=(((unsigned long)(*((c)++)))<<24))
 
 /* NOTE - c is not incremented as per c2l */
 #define c2ln(c,l1,l2,n)	{ \
 			c+=n; \
 			l1=l2=0; \
 			switch (n) { \
 			case 8: l2 =((unsigned long)(*(--(c))))<<24; \
 			case 7: l2|=((unsigned long)(*(--(c))))<<16; \
 			case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
 			case 5: l2|=((unsigned long)(*(--(c))));     \
 			case 4: l1 =((unsigned long)(*(--(c))))<<24; \
 			case 3: l1|=((unsigned long)(*(--(c))))<<16; \
 			case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
 			case 1: l1|=((unsigned long)(*(--(c))));     \
 				} \
 			}
 
 #define l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff))
 
 #define n2l(c,l)	(l =((unsigned long)(*((c)++)))<<24, \
 			 l|=((unsigned long)(*((c)++)))<<16, \
 			 l|=((unsigned long)(*((c)++)))<< 8, \
 			 l|=((unsigned long)(*((c)++))))
 
 #define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n6(l,c)	(*((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n8(l,c)	(*((c)++)=(unsigned char)(((l)>>56)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>48)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define n2l6(c,l)	(l =((BN_ULLONG)(*((c)++)))<<40, \
 			 l|=((BN_ULLONG)(*((c)++)))<<32, \
 			 l|=((BN_ULLONG)(*((c)++)))<<24, \
 			 l|=((BN_ULLONG)(*((c)++)))<<16, \
 			 l|=((BN_ULLONG)(*((c)++)))<< 8, \
 			 l|=((BN_ULLONG)(*((c)++))))
 
 /* NOTE - c is not incremented as per l2c */
 #define l2cn(l1,l2,c,n)	{ \
 			c+=n; \
 			switch (n) { \
 			case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
 			case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
 			case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
 			case 5: *(--(c))=(unsigned char)(((l2)    )&0xff); \
 			case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
 			case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
 			case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
 			case 1: *(--(c))=(unsigned char)(((l1)    )&0xff); \
 				} \
 			}
 
 #define n2s(c,s)	((s=(((unsigned int)(c[0]))<< 8)| \
 			    (((unsigned int)(c[1]))    )),c+=2)
 #define s2n(s,c)	((c[0]=(unsigned char)(((s)>> 8)&0xff), \
 			  c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
 
 #define n2l3(c,l)	((l =(((unsigned long)(c[0]))<<16)| \
 			     (((unsigned long)(c[1]))<< 8)| \
 			     (((unsigned long)(c[2]))    )),c+=3)
 
 #define l2n3(l,c)	((c[0]=(unsigned char)(((l)>>16)&0xff), \
 			  c[1]=(unsigned char)(((l)>> 8)&0xff), \
 			  c[2]=(unsigned char)(((l)    )&0xff)),c+=3)
 
 /* LOCAL STUFF */
 
 #define SSL_DECRYPT	0
 #define SSL_ENCRYPT	1
 
 #define TWO_BYTE_BIT	0x80
 #define SEC_ESC_BIT	0x40
 #define TWO_BYTE_MASK	0x7fff
 #define THREE_BYTE_MASK	0x3fff
 
 #define INC32(a)	((a)=((a)+1)&0xffffffffL)
 #define DEC32(a)	((a)=((a)-1)&0xffffffffL)
 #define MAX_MAC_SIZE	20 /* up from 16 for SSLv3 */
 
 /*
  * Define the Bitmasks for SSL_CIPHER.algorithms.
  * This bits are used packed as dense as possible. If new methods/ciphers
  * etc will be added, the bits a likely to change, so this information
  * is for internal library use only, even though SSL_CIPHER.algorithms
  * can be publicly accessed.
  * Use the according functions for cipher management instead.
  *
  * The bit mask handling in the selection and sorting scheme in
  * ssl_create_cipher_list() has only limited capabilities, reflecting
  * that the different entities within are mutually exclusive:
  * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
  */
 #define SSL_MKEY_MASK		0x000000FFL
 #define SSL_kRSA		0x00000001L /* RSA key exchange */
 #define SSL_kDHr		0x00000002L /* DH cert RSA CA cert */
 #define SSL_kDHd		0x00000004L /* DH cert DSA CA cert */
 #define SSL_kFZA		0x00000008L
 #define SSL_kEDH		0x00000010L /* tmp DH key no DH cert */
 #define SSL_kKRB5		0x00000020L /* Kerberos5 key exchange */
 #define SSL_kECDH               0x00000040L /* ECDH w/ long-term keys */
 #define SSL_kECDHE              0x00000080L /* ephemeral ECDH */
 #define SSL_EDH			(SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL))
 
 #define SSL_AUTH_MASK		0x00007F00L
 #define SSL_aRSA		0x00000100L /* Authenticate with RSA */
 #define SSL_aDSS 		0x00000200L /* Authenticate with DSS */
 #define SSL_DSS 		SSL_aDSS
 #define SSL_aFZA 		0x00000400L
 #define SSL_aNULL 		0x00000800L /* no Authenticate, ADH */
 #define SSL_aDH 		0x00001000L /* no Authenticate, ADH */
 #define SSL_aKRB5               0x00002000L /* Authenticate with KRB5 */
 #define SSL_aECDSA              0x00004000L /* Authenticate with ECDSA */
 
 #define SSL_NULL		(SSL_eNULL)
 #define SSL_ADH			(SSL_kEDH|SSL_aNULL)
 #define SSL_RSA			(SSL_kRSA|SSL_aRSA)
 #define SSL_DH			(SSL_kDHr|SSL_kDHd|SSL_kEDH)
 #define SSL_ECDH		(SSL_kECDH|SSL_kECDHE)
 #define SSL_FZA			(SSL_aFZA|SSL_kFZA|SSL_eFZA)
 #define SSL_KRB5                (SSL_kKRB5|SSL_aKRB5)
 
 #define SSL_ENC_MASK		0x1C3F8000L
 #define SSL_DES			0x00008000L
 #define SSL_3DES		0x00010000L
 #define SSL_RC4			0x00020000L
 #define SSL_RC2			0x00040000L
 #define SSL_IDEA		0x00080000L
 #define SSL_eFZA		0x00100000L
 #define SSL_eNULL		0x00200000L
 #define SSL_AES			0x04000000L
 #define SSL_CAMELLIA		0x08000000L
 #define SSL_SEED          	0x10000000L
 
 #define SSL_MAC_MASK		0x00c00000L
 #define SSL_MD5			0x00400000L
 #define SSL_SHA1		0x00800000L
 #define SSL_SHA			(SSL_SHA1)
 
 #define SSL_SSL_MASK		0x03000000L
 #define SSL_SSLV2		0x01000000L
 #define SSL_SSLV3		0x02000000L
 #define SSL_TLSV1		SSL_SSLV3	/* for now */
 
 /* we have used 1fffffff - 3 bits left to go. */
 
 /*
  * Export and cipher strength information. For each cipher we have to decide
  * whether it is exportable or not. This information is likely to change
  * over time, since the export control rules are no static technical issue.
  *
  * Independent of the export flag the cipher strength is sorted into classes.
  * SSL_EXP40 was denoting the 40bit US export limit of past times, which now
  * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change
  * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more,
  * since SSL_EXP64 could be similar to SSL_LOW.
  * For this reason SSL_MICRO and SSL_MINI macros are included to widen the
  * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed
  * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would
  * be possible.
  */
 #define SSL_EXP_MASK		0x00000003L
 #define SSL_NOT_EXP		0x00000001L
 #define SSL_EXPORT		0x00000002L
 
 #define SSL_STRONG_MASK		0x000000fcL
 #define SSL_STRONG_NONE		0x00000004L
 #define SSL_EXP40		0x00000008L
 #define SSL_MICRO		(SSL_EXP40)
 #define SSL_EXP56		0x00000010L
 #define SSL_MINI		(SSL_EXP56)
 #define SSL_LOW			0x00000020L
 #define SSL_MEDIUM		0x00000040L
 #define SSL_HIGH		0x00000080L
 #define SSL_FIPS		0x00000100L
 
 /* we have used 000001ff - 23 bits left to go */
 
 /*
  * Macros to check the export status and cipher strength for export ciphers.
  * Even though the macros for EXPORT and EXPORT40/56 have similar names,
  * their meaning is different:
  * *_EXPORT macros check the 'exportable' status.
  * *_EXPORT40/56 macros are used to check whether a certain cipher strength
  *          is given.
  * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct
  * algorithm structure element to be passed (algorithms, algo_strength) and no
  * typechecking can be done as they are all of type unsigned long, their
  * direct usage is discouraged.
  * Use the SSL_C_* macros instead.
  */
 #define SSL_IS_EXPORT(a)	((a)&SSL_EXPORT)
 #define SSL_IS_EXPORT56(a)	((a)&SSL_EXP56)
 #define SSL_IS_EXPORT40(a)	((a)&SSL_EXP40)
 #define SSL_C_IS_EXPORT(c)	SSL_IS_EXPORT((c)->algo_strength)
 #define SSL_C_IS_EXPORT56(c)	SSL_IS_EXPORT56((c)->algo_strength)
 #define SSL_C_IS_EXPORT40(c)	SSL_IS_EXPORT40((c)->algo_strength)
 
 #define SSL_EXPORT_KEYLENGTH(a,s)	(SSL_IS_EXPORT40(s) ? 5 : \
 				 ((a)&SSL_ENC_MASK) == SSL_DES ? 8 : 7)
 #define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024)
 #define SSL_C_EXPORT_KEYLENGTH(c)	SSL_EXPORT_KEYLENGTH((c)->algorithms, \
 				(c)->algo_strength)
 #define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
 
 
 #define SSL_ALL			0xffffffffL
 #define SSL_ALL_CIPHERS		(SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|\
 				SSL_MAC_MASK)
 #define SSL_ALL_STRENGTHS	(SSL_EXP_MASK|SSL_STRONG_MASK)
 
 /* Mostly for SSLv3 */
 #define SSL_PKEY_RSA_ENC	0
 #define SSL_PKEY_RSA_SIGN	1
 #define SSL_PKEY_DSA_SIGN	2
 #define SSL_PKEY_DH_RSA		3
 #define SSL_PKEY_DH_DSA		4
 #define SSL_PKEY_ECC            5
 #define SSL_PKEY_NUM		6
 
 /* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) |
  * 	    <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN)
  * SSL_kDH  <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
  * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN
  * SSL_aRSA <- RSA_ENC | RSA_SIGN
  * SSL_aDSS <- DSA_SIGN
  */
 
 /*
 #define CERT_INVALID		0
 #define CERT_PUBLIC_KEY		1
 #define CERT_PRIVATE_KEY	2
 */
 
 #ifndef OPENSSL_NO_EC
 /* From ECC-TLS draft, used in encoding the curve type in 
  * ECParameters
  */
 #define EXPLICIT_PRIME_CURVE_TYPE  1   
 #define EXPLICIT_CHAR2_CURVE_TYPE  2
 #define NAMED_CURVE_TYPE           3
 #endif  /* OPENSSL_NO_EC */
 
 typedef struct cert_pkey_st
 	{
 	X509 *x509;
 	EVP_PKEY *privatekey;
 	} CERT_PKEY;
 
 typedef struct cert_st
 	{
 	/* Current active set */
 	CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
 			 * Probably it would make more sense to store
 			 * an index, not a pointer. */
  
 	/* The following masks are for the key and auth
 	 * algorithms that are supported by the certs below */
 	int valid;
 	unsigned long mask;
 	unsigned long export_mask;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa_tmp;
 	RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh_tmp;
 	DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh_tmp;
 	/* Callback for generating ephemeral ECDH keys */
 	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 
 	CERT_PKEY pkeys[SSL_PKEY_NUM];
 
 	int references; /* >1 only if SSL_copy_session_id is used */
 	} CERT;
 
 
 typedef struct sess_cert_st
 	{
 	STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */
 
 	/* The 'peer_...' members are used only by clients. */
 	int peer_cert_type;
 
 	CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */
 	CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
 	/* Obviously we don't have the private keys of these,
 	 * so maybe we shouldn't even use the CERT_PKEY type here. */
 
 #ifndef OPENSSL_NO_RSA
 	RSA *peer_rsa_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *peer_dh_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *peer_ecdh_tmp;
 #endif
 
 	int references; /* actually always 1 at the moment */
 	} SESS_CERT;
 
 
 /*#define MAC_DEBUG	*/
 
 /*#define ERR_DEBUG	*/
 /*#define ABORT_DEBUG	*/
 /*#define PKT_DEBUG 1   */
 /*#define DES_DEBUG	*/
 /*#define DES_OFB_DEBUG	*/
 /*#define SSL_DEBUG	*/
 /*#define RSA_DEBUG	*/ 
 /*#define IDEA_DEBUG	*/ 
 
 #define FP_ICC  (int (*)(const void *,const void *))
 #define ssl_put_cipher_by_char(ssl,ciph,ptr) \
 		((ssl)->method->put_cipher_by_char((ciph),(ptr)))
 #define ssl_get_cipher_by_char(ssl,ptr) \
 		((ssl)->method->get_cipher_by_char(ptr))
 
 /* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff
  * It is a bit of a mess of functions, but hell, think of it as
  * an opaque structure :-) */
 typedef struct ssl3_enc_method
 	{
 	int (*enc)(SSL *, int);
 	int (*mac)(SSL *, unsigned char *, int);
 	int (*setup_key_block)(SSL *);
 	int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int);
 	int (*change_cipher_state)(SSL *, int);
 	int (*final_finish_mac)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char *, int, unsigned char *);
 	int finish_mac_length;
 	int (*cert_verify_mac)(SSL *, EVP_MD_CTX *, unsigned char *);
 	const char *client_finished_label;
 	int client_finished_label_len;
 	const char *server_finished_label;
 	int server_finished_label_len;
 	int (*alert_value)(int);
 	} SSL3_ENC_METHOD;
 
 #ifndef OPENSSL_NO_COMP
 /* Used for holding the relevant compression methods loaded into SSL_CTX */
 typedef struct ssl3_comp_st
 	{
 	int comp_id;	/* The identifier byte for this compression type */
 	char *name;	/* Text name used for the compression type */
 	COMP_METHOD *method; /* The method :-) */
 	} SSL3_COMP;
 #endif
 
 extern SSL3_ENC_METHOD ssl3_undef_enc_method;
 OPENSSL_EXTERN SSL_CIPHER ssl2_ciphers[];
 OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[];
 
 
 SSL_METHOD *ssl_bad_method(int ver);
 SSL_METHOD *sslv2_base_method(void);
 SSL_METHOD *sslv23_base_method(void);
 SSL_METHOD *sslv3_base_method(void);
 
 extern SSL3_ENC_METHOD TLSv1_enc_data;
 extern SSL3_ENC_METHOD SSLv3_enc_data;
 extern SSL3_ENC_METHOD DTLSv1_enc_data;
 
 #define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		TLS1_VERSION, \
 		tls1_new, \
 		tls1_clear, \
 		tls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		tls1_default_timeout, \
 		&TLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		SSL3_VERSION, \
 		ssl3_new, \
 		ssl3_clear, \
 		ssl3_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		ssl3_default_timeout, \
 		&SSLv3_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 	TLS1_VERSION, \
 	tls1_new, \
 	tls1_clear, \
 	tls1_free, \
 	s_accept, \
 	s_connect, \
 	ssl23_read, \
 	ssl23_peek, \
 	ssl23_write, \
 	ssl_undefined_function, \
 	ssl_undefined_function, \
 	ssl_ok, \
 	ssl3_get_message, \
 	ssl3_read_bytes, \
 	ssl3_write_bytes, \
 	ssl3_dispatch_alert, \
 	ssl3_ctrl, \
 	ssl3_ctx_ctrl, \
 	ssl23_get_cipher_by_char, \
 	ssl23_put_cipher_by_char, \
 	ssl_undefined_const_function, \
 	ssl23_num_ciphers, \
 	ssl23_get_cipher, \
 	s_get_meth, \
 	ssl23_default_timeout, \
 	&ssl3_undef_enc_method, \
 	ssl_undefined_void_function, \
 	ssl3_callback_ctrl, \
 	ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl2_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		SSL2_VERSION, \
 		ssl2_new,	/* local */ \
 		ssl2_clear,	/* local */ \
 		ssl2_free,	/* local */ \
 		s_accept, \
 		s_connect, \
 		ssl2_read, \
 		ssl2_peek, \
 		ssl2_write, \
 		ssl2_shutdown, \
 		ssl_ok,	/* NULL - renegotiate */ \
 		ssl_ok,	/* NULL - check renegotiate */ \
 		NULL, /* NULL - ssl_get_message */ \
 		NULL, /* NULL - ssl_get_record */ \
 		NULL, /* NULL - ssl_write_bytes */ \
 		NULL, /* NULL - dispatch_alert */ \
 		ssl2_ctrl,	/* local */ \
 		ssl2_ctx_ctrl,	/* local */ \
 		ssl2_get_cipher_by_char, \
 		ssl2_put_cipher_by_char, \
 		ssl2_pending, \
 		ssl2_num_ciphers, \
 		ssl2_get_cipher, \
 		s_get_meth, \
 		ssl2_default_timeout, \
 		&ssl3_undef_enc_method, \
 		ssl_undefined_void_function, \
 		ssl2_callback_ctrl,	/* local */ \
 		ssl2_ctx_callback_ctrl,	/* local */ \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		DTLS1_VERSION, \
 		dtls1_new, \
 		dtls1_clear, \
 		dtls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		dtls1_get_message, \
 		dtls1_read_bytes, \
 		dtls1_write_app_data_bytes, \
 		dtls1_dispatch_alert, \
 		dtls1_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		dtls1_get_cipher, \
 		s_get_meth, \
 		dtls1_default_timeout, \
 		&DTLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 void ssl_clear_cipher_ctx(SSL *s);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
 int ssl_cert_inst(CERT **o);
 void ssl_cert_free(CERT *c);
 SESS_CERT *ssl_sess_cert_new(void);
 void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
 			const SSL_CIPHER * const *bp);
 STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
 					       STACK_OF(SSL_CIPHER) **skp);
 int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                              int (*put_cb)(const SSL_CIPHER *, unsigned char *));
 STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
 					     STACK_OF(SSL_CIPHER) **pref,
 					     STACK_OF(SSL_CIPHER) **sorted,
 					     const char *rule_str);
 void ssl_update_cache(SSL *s, int mode);
 int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
 		       const EVP_MD **md,SSL_COMP **comp);
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);
 CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
 X509 *ssl_get_server_send_cert(const SSL *);
 EVP_PKEY *ssl_get_sign_pkey(SSL *,SSL_CIPHER *);
 int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
 void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher);
 STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
 int ssl_verify_alarm_type(long type);
 void ssl_load_ciphers(void);
 
 int ssl2_enc_init(SSL *s, int client);
 int ssl2_generate_key_material(SSL *s);
 void ssl2_enc(SSL *s,int send_data);
 void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
 SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
 int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 int ssl2_part_read(SSL *s, unsigned long f, int i);
 int ssl2_do_write(SSL *s);
 int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
 void ssl2_return_error(SSL *s,int reason);
 void ssl2_write_error(SSL *s);
 int ssl2_num_ciphers(void);
 SSL_CIPHER *ssl2_get_cipher(unsigned int u);
 int	ssl2_new(SSL *s);
 void	ssl2_free(SSL *s);
 int	ssl2_accept(SSL *s);
 int	ssl2_connect(SSL *s);
 int	ssl2_read(SSL *s, void *buf, int len);
 int	ssl2_peek(SSL *s, void *buf, int len);
 int	ssl2_write(SSL *s, const void *buf, int len);
 int	ssl2_shutdown(SSL *s);
 void	ssl2_clear(SSL *s);
 long	ssl2_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl2_pending(const SSL *s);
 long	ssl2_default_timeout(void );
 
 SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
 int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 void ssl3_init_finished_mac(SSL *s);
 int ssl3_send_server_certificate(SSL *s);
 int ssl3_send_newsession_ticket(SSL *s);
 int ssl3_send_cert_status(SSL *s);
 int ssl3_get_finished(SSL *s,int state_a,int state_b);
 int ssl3_setup_key_block(SSL *s);
 int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
 int ssl3_change_cipher_state(SSL *s,int which);
 void ssl3_cleanup_key_block(SSL *s);
 int ssl3_do_write(SSL *s,int type);
 int ssl3_send_alert(SSL *s,int level, int desc);
 int ssl3_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int ssl3_get_req_cert_type(SSL *s,unsigned char *p);
 long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen);
 int ssl3_num_ciphers(void);
 SSL_CIPHER *ssl3_get_cipher(unsigned int u);
 int ssl3_renegotiate(SSL *ssl); 
 int ssl3_renegotiate_check(SSL *ssl); 
 int ssl3_dispatch_alert(SSL *s);
 int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
 int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1, EVP_MD_CTX *ctx2,
 	const char *sender, int slen,unsigned char *p);
 int ssl3_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p);
 void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
 int ssl3_enc(SSL *s, int send_data);
 int ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
 unsigned long ssl3_output_cert_chain(SSL *s, X509 *x);
 SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt,
 			       STACK_OF(SSL_CIPHER) *srvr);
 int	ssl3_setup_buffers(SSL *s);
 int	ssl3_new(SSL *s);
 void	ssl3_free(SSL *s);
 int	ssl3_accept(SSL *s);
 int	ssl3_connect(SSL *s);
 int	ssl3_read(SSL *s, void *buf, int len);
 int	ssl3_peek(SSL *s, void *buf, int len);
 int	ssl3_write(SSL *s, const void *buf, int len);
 int	ssl3_shutdown(SSL *s);
 void	ssl3_clear(SSL *s);
 long	ssl3_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl3_pending(const SSL *s);
 
 void ssl3_record_sequence_update(unsigned char *seq);
 int ssl3_do_change_cipher_spec(SSL *ssl);
 long ssl3_default_timeout(void );
 
 int ssl23_num_ciphers(void );
 SSL_CIPHER *ssl23_get_cipher(unsigned int u);
 int ssl23_read(SSL *s, void *buf, int len);
 int ssl23_peek(SSL *s, void *buf, int len);
 int ssl23_write(SSL *s, const void *buf, int len);
 int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
 SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p);
 long ssl23_default_timeout(void );
 
 long tls1_default_timeout(void);
 int dtls1_do_write(SSL *s,int type);
 int ssl3_read_n(SSL *s, int n, int max, int extend);
 int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_do_compress(SSL *ssl);
 int ssl3_do_uncompress(SSL *ssl);
 int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
 	unsigned int len);
 unsigned char *dtls1_set_message_header(SSL *s, 
 	unsigned char *p, unsigned char mt,	unsigned long len, 
 	unsigned long frag_off, unsigned long frag_len);
 
 int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
 int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
 
 int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
 int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
 unsigned long dtls1_output_cert_chain(SSL *s, X509 *x);
 int dtls1_read_failed(SSL *s, int code);
 int dtls1_buffer_message(SSL *s, int ccs);
 int dtls1_retransmit_message(SSL *s, unsigned short seq, 
 	unsigned long frag_off, int *found);
 int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
 int dtls1_retransmit_buffered_messages(SSL *s);
 void dtls1_clear_record_buffer(SSL *s);
 void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
 void dtls1_reset_seq_numbers(SSL *s, int rw);
 long dtls1_default_timeout(void);
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
 int dtls1_check_timeout_num(SSL *s);
 int dtls1_handle_timeout(SSL *s);
 SSL_CIPHER *dtls1_get_cipher(unsigned int u);
 void dtls1_start_timer(SSL *s);
 void dtls1_stop_timer(SSL *s);
 int dtls1_is_timer_expired(SSL *s);
 void dtls1_double_timeout(SSL *s);
 int dtls1_send_newsession_ticket(SSL *s);
 unsigned int dtls1_min_mtu(void);
 
 
 /* some client-only functions */
 int ssl3_client_hello(SSL *s);
 int ssl3_get_server_hello(SSL *s);
 int ssl3_get_certificate_request(SSL *s);
 int ssl3_get_new_session_ticket(SSL *s);
 int ssl3_get_cert_status(SSL *s);
 int ssl3_get_server_done(SSL *s);
 int ssl3_send_client_verify(SSL *s);
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
 int ssl3_send_client_certificate(SSL *s);
 int ssl3_send_client_key_exchange(SSL *s);
 int ssl3_get_key_exchange(SSL *s);
 int ssl3_get_server_certificate(SSL *s);
 int ssl3_check_cert_and_algorithm(SSL *s);
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_check_finished(SSL *s);
 #endif
 
 int dtls1_client_hello(SSL *s);
 int dtls1_send_client_certificate(SSL *s);
 int dtls1_send_client_key_exchange(SSL *s);
 int dtls1_send_client_verify(SSL *s);
 
 /* some server-only functions */
 int ssl3_get_client_hello(SSL *s);
 int ssl3_send_server_hello(SSL *s);
 int ssl3_send_hello_request(SSL *s);
 int ssl3_send_server_key_exchange(SSL *s);
 int ssl3_send_certificate_request(SSL *s);
 int ssl3_send_server_done(SSL *s);
 int ssl3_check_client_hello(SSL *s);
 int ssl3_get_client_certificate(SSL *s);
 int ssl3_get_client_key_exchange(SSL *s);
 int ssl3_get_cert_verify(SSL *s);
 
 int dtls1_send_hello_request(SSL *s);
 int dtls1_send_server_hello(SSL *s);
 int dtls1_send_server_certificate(SSL *s);
 int dtls1_send_server_key_exchange(SSL *s);
 int dtls1_send_certificate_request(SSL *s);
 int dtls1_send_server_done(SSL *s);
 
 
 
 int ssl23_accept(SSL *s);
 int ssl23_connect(SSL *s);
 int ssl23_read_bytes(SSL *s, int n);
 int ssl23_write_bytes(SSL *s);
 
 int tls1_new(SSL *s);
 void tls1_free(SSL *s);
 void tls1_clear(SSL *s);
 long tls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 SSL_METHOD *tlsv1_base_method(void );
 
 int dtls1_new(SSL *s);
 int	dtls1_accept(SSL *s);
 int	dtls1_connect(SSL *s);
 void dtls1_free(SSL *s);
 void dtls1_clear(SSL *s);
 long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 SSL_METHOD *dtlsv1_base_method(void );
 
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int dtls1_get_record(SSL *s);
 int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
 	unsigned int len, int create_empty_fragement);
 int dtls1_dispatch_alert(SSL *s);
 int dtls1_enc(SSL *s, int snd);
 
 int ssl_init_wbio_buffer(SSL *s, int push);
 void ssl_free_wbio_buffer(SSL *s);
 
 int tls1_change_cipher_state(SSL *s, int which);
 int tls1_setup_key_block(SSL *s);
 int tls1_enc(SSL *s, int snd);
 int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx,
 	const char *str, int slen, unsigned char *p);
 int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p);
 int tls1_mac(SSL *ssl, unsigned char *md, int snd);
 int tls1_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int tls1_alert_code(int code);
 int ssl3_alert_code(int code);
 int ssl_ok(SSL *s);
 
 int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
 
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
 
 #ifndef OPENSSL_NO_TLSEXT
 unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_prepare_clienthello_tlsext(SSL *s);
 int ssl_prepare_serverhello_tlsext(SSL *s);
 int ssl_check_clienthello_tlsext_early(SSL *s);
 int ssl_check_clienthello_tlsext_late(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
 
 #ifdef OPENSSL_NO_SHA256
 #define tlsext_tick_md	EVP_sha1
 #else
 #define tlsext_tick_md	EVP_sha256
 #endif
 int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 				const unsigned char *limit, SSL_SESSION **ret);
 EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 
 int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 #endif
 /* s3_cbc.c */
 void ssl3_cbc_copy_mac(unsigned char* out,
 		       const SSL3_RECORD *rec,
 		       unsigned md_size,unsigned orig_len);
 int ssl3_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 int tls1_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 char ssl3_cbc_record_digest_supported(const EVP_MD *hash);
 void ssl3_cbc_digest_record(
 	const EVP_MD *hash,
 	unsigned char* md_out,
 	size_t* md_out_size,
 	const unsigned char header[13],
 	const unsigned char *data,
 	size_t data_plus_mac_size,
 	size_t data_plus_mac_plus_padding_size,
 	const unsigned char *mac_secret,
 	unsigned mac_secret_length,
 	char is_sslv3);
 
 void tls_fips_digest_extra(
 	const EVP_CIPHER_CTX *cipher_ctx, const EVP_MD *hash, HMAC_CTX *hctx,
 	const unsigned char *data, size_t data_len, size_t orig_len);
 
 #endif
Index: releng/8.4/crypto/openssl/ssl/ssl_sess.c
===================================================================
--- releng/8.4/crypto/openssl/ssl/ssl_sess.c	(revision 284294)
+++ releng/8.4/crypto/openssl/ssl/ssl_sess.c	(revision 284295)
@@ -1,911 +1,984 @@
 /* ssl/ssl_sess.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include "ssl_locl.h"
 
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
 
 SSL_SESSION *SSL_get_session(const SSL *ssl)
 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
 	{
 	return(ssl->session);
 	}
 
 SSL_SESSION *SSL_get1_session(SSL *ssl)
 /* variant of SSL_get_session: caller really gets something */
 	{
 	SSL_SESSION *sess;
 	/* Need to lock this all up rather than just use CRYPTO_add so that
 	 * somebody doesn't free ssl->session between when we check it's
 	 * non-null and when we up the reference count. */
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
 	sess = ssl->session;
 	if(sess)
 		sess->references++;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
 	return(sess);
 	}
 
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
 	{
 	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
 	}
 
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
 	{
 	return(CRYPTO_get_ex_data(&s->ex_data,idx));
 	}
 
 SSL_SESSION *SSL_SESSION_new(void)
 	{
 	SSL_SESSION *ss;
 
 	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
 	if (ss == NULL)
 		{
 		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	memset(ss,0,sizeof(SSL_SESSION));
 
 	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
 	ss->references=1;
 	ss->timeout=60*5+4; /* 5 minute timeout by default */
 	ss->time=(unsigned long)time(NULL);
 	ss->prev=NULL;
 	ss->next=NULL;
 	ss->compress_meth=0;
 #ifndef OPENSSL_NO_TLSEXT
 	ss->tlsext_hostname = NULL; 
 #endif
 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 	return(ss);
 	}
 
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+    /*
+     * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+#endif
+    dest->tlsext_tick = NULL;
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)
 		*len = s->session_id_length;
 	return s->session_id;
 	}
 
 /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
  * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
  * until we have no conflict is going to complete in one iteration pretty much
  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  * and we still can't avoid a conflict - well that's a reasonable point to call
  * it quits. Either the RAND code is broken or someone is trying to open roughly
  * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
  * store that many sessions is perhaps a more interesting question ... */
 
 #define MAX_SESS_ID_ATTEMPTS 10
 static int def_generate_session_id(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len)
 {
 	unsigned int retry = 0;
 	do
 		if (RAND_pseudo_bytes(id, *id_len) <= 0)
 			return 0;
 	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
 		(++retry < MAX_SESS_ID_ATTEMPTS));
 	if(retry < MAX_SESS_ID_ATTEMPTS)
 		return 1;
 	/* else - woops a session_id match */
 	/* XXX We should also check the external cache --
 	 * but the probability of a collision is negligible, and
 	 * we could not prevent the concurrent creation of sessions
 	 * with identical IDs since we currently don't have means
 	 * to atomically check whether a session ID already exists
 	 * and make a reservation for it if it does not
 	 * (this problem applies to the internal cache as well).
 	 */
 	return 0;
 }
 
 int ssl_get_new_session(SSL *s, int session)
 	{
 	/* This gets used by clients and servers. */
 
 	unsigned int tmp;
 	SSL_SESSION *ss=NULL;
 	GEN_SESSION_CB cb = def_generate_session_id;
 
 	if ((ss=SSL_SESSION_new()) == NULL) return(0);
 
 	/* If the context has a default timeout, use it */
 	if (s->ctx->session_timeout == 0)
 		ss->timeout=SSL_get_default_timeout(s);
 	else
 		ss->timeout=s->ctx->session_timeout;
 
 	if (s->session != NULL)
 		{
 		SSL_SESSION_free(s->session);
 		s->session=NULL;
 		}
 
 	if (session)
 		{
 		if (s->version == SSL2_VERSION)
 			{
 			ss->ssl_version=SSL2_VERSION;
 			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == SSL3_VERSION)
 			{
 			ss->ssl_version=SSL3_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == TLS1_VERSION)
 			{
 			ss->ssl_version=TLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_BAD_VER)
 			{
 			ss->ssl_version=DTLS1_BAD_VER;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_VERSION)
 			{
 			ss->ssl_version=DTLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		/* If RFC4507 ticket use empty session ID */
 		if (s->tlsext_ticket_expected)
 			{
 			ss->session_id_length = 0;
 			goto sess_id_done;
 			}
 #endif
 		/* Choose which callback will set the session ID */
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		if(s->generate_session_id)
 			cb = s->generate_session_id;
 		else if(s->ctx->generate_session_id)
 			cb = s->ctx->generate_session_id;
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		/* Choose a session ID */
 		tmp = ss->session_id_length;
 		if(!cb(s, ss->session_id, &tmp))
 			{
 			/* The callback failed */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* Don't allow the callback to set the session length to zero.
 		 * nor set it higher than it was. */
 		if(!tmp || (tmp > ss->session_id_length))
 			{
 			/* The callback set an illegal length */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* If the session length was shrunk and we're SSLv2, pad it */
 		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
 			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
 		else
 			ss->session_id_length = tmp;
 		/* Finally, check for a conflict */
 		if(SSL_has_matching_session_id(s, ss->session_id,
 						ss->session_id_length))
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CONFLICT);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		sess_id_done:
 		if (s->tlsext_hostname) {
 			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
 			if (ss->tlsext_hostname == NULL) {
 				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 				SSL_SESSION_free(ss);
 				return 0;
 				}
 			}
 #endif
 		}
 	else
 		{
 		ss->session_id_length=0;
 		}
 
 	if (s->sid_ctx_length > sizeof ss->sid_ctx)
 		{
 		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 		SSL_SESSION_free(ss);
 		return 0;
 		}
 	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
 	ss->sid_ctx_length=s->sid_ctx_length;
 	s->session=ss;
 	ss->ssl_version=s->version;
 	ss->verify_result = X509_V_OK;
 
 	return(1);
 	}
 
 int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
 			const unsigned char *limit)
 	{
 	/* This is used only by servers. */
 
 	SSL_SESSION *ret=NULL;
 	int fatal = 0;
 #ifndef OPENSSL_NO_TLSEXT
 	int r;
 #endif
   
 	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
 		goto err;
 #ifndef OPENSSL_NO_TLSEXT
  	r = tls1_process_ticket(s, session_id, len, limit, &ret);
 	if (r == -1)
 		{
 		fatal = 1;
  		goto err;
 		}
 	else if (r == 0 || (!ret && !len))
 		goto err;
 	else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 #else
 	if (len == 0)
 		goto err;
 	if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 #endif
 		{
 		SSL_SESSION data;
 		data.ssl_version=s->version;
 		data.session_id_length=len;
 		if (len == 0)
 			return 0;
  		memcpy(data.session_id,session_id,len);
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
 		if (ret != NULL)
 		    /* don't allow other threads to steal it: */
 		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		}
 
 	if (ret == NULL)
 		{
 		int copy=1;
 	
 		s->ctx->stats.sess_miss++;
 		ret=NULL;
 		if (s->ctx->get_session_cb != NULL
 		    && (ret=s->ctx->get_session_cb(s,session_id,len,©))
 		       != NULL)
 			{
 			s->ctx->stats.sess_cb_hit++;
 
 			/* Increment reference count now if the session callback
 			 * asks us to do so (note that if the session structures
 			 * returned by the callback are shared between threads,
 			 * it must handle the reference count itself [i.e. copy == 0],
 			 * or things won't be thread-safe). */
 			if (copy)
 				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 
 			/* Add the externally cached session to the internal
 			 * cache as well if and only if we are supposed to. */
 			if(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
 				/* The following should not return 1, otherwise,
 				 * things are very strange */
 				SSL_CTX_add_session(s->ctx,ret);
 			}
 		if (ret == NULL)
 			goto err;
 		}
 
 	/* Now ret is non-NULL, and we own one of its reference counts. */
 
 	if (ret->sid_ctx_length != s->sid_ctx_length
 	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
 		{
 		/* We've found the session named by the client, but we don't
 		 * want to use it in this context. */
 
 #if 0 /* The client cannot always know when a session is not appropriate,
        * so we shouldn't generate an error message. */
 
 		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 #endif
 		goto err; /* treat like cache miss */
 		}
 	
 	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
 		{
 		/* We can't be sure if this session is being used out of
 		 * context, which is especially important for SSL_VERIFY_PEER.
 		 * The application should have used SSL[_CTX]_set_session_id_context.
 		 *
 		 * For this error case, we generate an error instead of treating
 		 * the event like a cache miss (otherwise it would be easy for
 		 * applications to effectively disable the session cache by
 		 * accident without anyone noticing).
 		 */
 		
 		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
 		fatal = 1;
 		goto err;
 		}
 
 	if (ret->cipher == NULL)
 		{
 		unsigned char buf[5],*p;
 		unsigned long l;
 
 		p=buf;
 		l=ret->cipher_id;
 		l2n(l,p);
 		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR)
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
 		else 
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
 		if (ret->cipher == NULL)
 			goto err;
 		}
 
 
 #if 0 /* This is way too late. */
 
 	/* If a thread got the session, then 'swaped', and another got
 	 * it and then due to a time-out decided to 'OPENSSL_free' it we could
 	 * be in trouble.  So I'll increment it now, then double decrement
 	 * later - am I speaking rubbish?. */
 	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 #endif
 
 	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
 		{
 		s->ctx->stats.sess_timeout++;
 		/* remove it from the cache */
 		SSL_CTX_remove_session(s->ctx,ret);
 		goto err;
 		}
 
 	s->ctx->stats.sess_hit++;
 
 	/* ret->time=time(NULL); */ /* rezero timeout? */
 	/* again, just leave the session 
 	 * if it is the same session, we have just incremented and
 	 * then decremented the reference count :-) */
 	if (s->session != NULL)
 		SSL_SESSION_free(s->session);
 	s->session=ret;
 	s->verify_result = s->session->verify_result;
 	return(1);
 
  err:
 	if (ret != NULL)
 		SSL_SESSION_free(ret);
 	if (fatal)
 		return -1;
 	else
 		return 0;
 	}
 
 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
 	{
 	int ret=0;
 	SSL_SESSION *s;
 
 	/* add just 1 reference count for the SSL_CTX's session cache
 	 * even though it has two ways of access: each session is in a
 	 * doubly linked list and an lhash */
 	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
 	/* if session c is in already in cache, we take back the increment later */
 
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	s=(SSL_SESSION *)lh_insert(ctx->sessions,c);
 	
 	/* s != NULL iff we already had a session with the given PID.
 	 * In this case, s == c should hold (then we did not really modify
 	 * ctx->sessions), or we're in trouble. */
 	if (s != NULL && s != c)
 		{
 		/* We *are* in trouble ... */
 		SSL_SESSION_list_remove(ctx,s);
 		SSL_SESSION_free(s);
 		/* ... so pretend the other session did not exist in cache
 		 * (we cannot handle two SSL_SESSION structures with identical
 		 * session ID in the same cache, which could happen e.g. when
 		 * two threads concurrently obtain the same session from an external
 		 * cache) */
 		s = NULL;
 		}
 
  	/* Put at the head of the queue unless it is already in the cache */
 	if (s == NULL)
 		SSL_SESSION_list_add(ctx,c);
 
 	if (s != NULL)
 		{
 		/* existing cache entry -- decrement previously incremented reference
 		 * count because it already takes into account the cache */
 
 		SSL_SESSION_free(s); /* s == c */
 		ret=0;
 		}
 	else
 		{
 		/* new cache entry -- remove old ones if cache has become too large */
 		
 		ret=1;
 
 		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
 			{
 			while (SSL_CTX_sess_number(ctx) >
 				SSL_CTX_sess_get_cache_size(ctx))
 				{
 				if (!remove_session_lock(ctx,
 					ctx->session_cache_tail, 0))
 					break;
 				else
 					ctx->stats.sess_cache_full++;
 				}
 			}
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	return(ret);
 	}
 
 int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
 {
 	return remove_session_lock(ctx, c, 1);
 }
 
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
 	{
 	SSL_SESSION *r;
 	int ret=0;
 
 	if ((c != NULL) && (c->session_id_length != 0))
 		{
 		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 		if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c)
 			{
 			ret=1;
 			r=(SSL_SESSION *)lh_delete(ctx->sessions,c);
 			SSL_SESSION_list_remove(ctx,c);
 			}
 
 		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 
 		if (ret)
 			{
 			r->not_resumable=1;
 			if (ctx->remove_session_cb != NULL)
 				ctx->remove_session_cb(ctx,r);
 			SSL_SESSION_free(r);
 			}
 		}
 	else
 		ret=0;
 	return(ret);
 	}
 
 void SSL_SESSION_free(SSL_SESSION *ss)
 	{
 	int i;
 
 	if(ss == NULL)
 	    return;
 
 	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
 #ifdef REF_PRINT
 	REF_PRINT("SSL_SESSION",ss);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
 		abort(); /* ok */
 		}
 #endif
 
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
 	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
 	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key);
 	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id);
 	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
 	if (ss->peer != NULL) X509_free(ss->peer);
 	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
 #ifndef OPENSSL_NO_TLSEXT
 	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
 	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
 #endif
 	OPENSSL_cleanse(ss,sizeof(*ss));
 	OPENSSL_free(ss);
 	}
 
 int SSL_set_session(SSL *s, SSL_SESSION *session)
 	{
 	int ret=0;
 	SSL_METHOD *meth;
 
 	if (session != NULL)
 		{
 		meth=s->ctx->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			meth=s->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			{
 			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
 			return(0);
 			}
 
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			if (s->ctx->session_timeout == 0)
 				session->timeout=SSL_get_default_timeout(s);
 			else
 				session->timeout=s->ctx->session_timeout;
 			}
 
 #ifndef OPENSSL_NO_KRB5
                 if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
                     session->krb5_client_princ_len > 0)
                 {
                     s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
                     memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
                             session->krb5_client_princ_len);
                     s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
                 }
 #endif /* OPENSSL_NO_KRB5 */
 
 		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
 		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
 		if (s->session != NULL)
 			SSL_SESSION_free(s->session);
 		s->session=session;
 		s->verify_result = s->session->verify_result;
 		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
 		ret=1;
 		}
 	else
 		{
 		if (s->session != NULL)
 			{
 			SSL_SESSION_free(s->session);
 			s->session=NULL;
 			}
 
 		meth=s->ctx->method;
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			}
 		ret=1;
 		}
 	return(ret);
 	}
 
 long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->timeout=t;
 	return(1);
 	}
 
 long SSL_SESSION_get_timeout(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->timeout);
 	}
 
 long SSL_SESSION_get_time(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->time);
 	}
 
 long SSL_SESSION_set_time(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->time=t;
 	return(t);
 	}
 
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
 	{
 	long l;
 	if (s == NULL) return(0);
 	l=s->session_timeout;
 	s->session_timeout=t;
 	return(l);
 	}
 
 long SSL_CTX_get_timeout(const SSL_CTX *s)
 	{
 	if (s == NULL) return(0);
 	return(s->session_timeout);
 	}
 
 typedef struct timeout_param_st
 	{
 	SSL_CTX *ctx;
 	long time;
 	LHASH *cache;
 	} TIMEOUT_PARAM;
 
 static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p)
 	{
 	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
 		{
 		/* The reason we don't call SSL_CTX_remove_session() is to
 		 * save on locking overhead */
 		lh_delete(p->cache,s);
 		SSL_SESSION_list_remove(p->ctx,s);
 		s->not_resumable=1;
 		if (p->ctx->remove_session_cb != NULL)
 			p->ctx->remove_session_cb(p->ctx,s);
 		SSL_SESSION_free(s);
 		}
 	}
 
 static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *)
 
 void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
 	{
 	unsigned long i;
 	TIMEOUT_PARAM tp;
 
 	tp.ctx=s;
 	tp.cache=s->sessions;
 	if (tp.cache == NULL) return;
 	tp.time=t;
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	i=tp.cache->down_load;
 	tp.cache->down_load=0;
 	lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp);
 	tp.cache->down_load=i;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	}
 
 int ssl_clear_bad_session(SSL *s)
 	{
 	if (	(s->session != NULL) &&
 		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
 		!(SSL_in_init(s) || SSL_in_before(s)))
 		{
 		SSL_CTX_remove_session(s->ctx,s->session);
 		return(1);
 		}
 	else
 		return(0);
 	}
 
 /* locked by SSL_CTX in the calling function */
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next == NULL) || (s->prev == NULL)) return;
 
 	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
 		{ /* last element in list */
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* only one element in list */
 			ctx->session_cache_head=NULL;
 			ctx->session_cache_tail=NULL;
 			}
 		else
 			{
 			ctx->session_cache_tail=s->prev;
 			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 			}
 		}
 	else
 		{
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* first element in list */
 			ctx->session_cache_head=s->next;
 			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 			}
 		else
 			{ /* middle of list */
 			s->next->prev=s->prev;
 			s->prev->next=s->next;
 			}
 		}
 	s->prev=s->next=NULL;
 	}
 
 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next != NULL) && (s->prev != NULL))
 		SSL_SESSION_list_remove(ctx,s);
 
 	if (ctx->session_cache_head == NULL)
 		{
 		ctx->session_cache_head=s;
 		ctx->session_cache_tail=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 		}
 	else
 		{
 		s->next=ctx->session_cache_head;
 		s->next->prev=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		ctx->session_cache_head=s;
 		}
 	}
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
 	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
 	{
 	ctx->new_session_cb=cb;
 	}
 
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
 	{
 	return ctx->new_session_cb;
 	}
 
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
 	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
 	{
 	ctx->remove_session_cb=cb;
 	}
 
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
 	{
 	return ctx->remove_session_cb;
 	}
 
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
 	SSL_SESSION *(*cb)(struct ssl_st *ssl,
 	         unsigned char *data,int len,int *copy))
 	{
 	ctx->get_session_cb=cb;
 	}
 
 SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
 	         unsigned char *data,int len,int *copy)
 	{
 	return ctx->get_session_cb;
 	}
 
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, 
 	void (*cb)(const SSL *ssl,int type,int val))
 	{
 	ctx->info_callback=cb;
 	}
 
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
 	{
 	return ctx->info_callback;
 	}
 
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
 	{
 	ctx->client_cert_cb=cb;
 	}
 
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
 	{
 	return ctx->client_cert_cb;
 	}
 
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
 	{
 	if (!ENGINE_init(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
 		return 0;
 		}
 	if(!ENGINE_get_ssl_client_cert_function(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
 		ENGINE_finish(e);
 		return 0;
 		}
 	ctx->client_cert_engine = e;
 	return 1;
 	}
 #endif
 
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
 	{
 	ctx->app_gen_cookie_cb=cb;
 	}
 
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
 	{
 	ctx->app_verify_cookie_cb=cb;
 	}
 
Index: releng/8.4/sys/conf/newvers.sh
===================================================================
--- releng/8.4/sys/conf/newvers.sh	(revision 284294)
+++ releng/8.4/sys/conf/newvers.sh	(revision 284295)
@@ -1,152 +1,152 @@
 #!/bin/sh -
 #
 # Copyright (c) 1984, 1986, 1990, 1993
 #	The Regents of the University of California.  All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
 # 1. Redistributions of source code must retain the above copyright
 #    notice, this list of conditions and the following disclaimer.
 # 2. Redistributions in binary form must reproduce the above copyright
 #    notice, this list of conditions and the following disclaimer in the
 #    documentation and/or other materials provided with the distribution.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
 #
 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
 #	@(#)newvers.sh	8.1 (Berkeley) 4/20/94
 # $FreeBSD$
 
 TYPE="FreeBSD"
 REVISION="8.4"
-BRANCH="RELEASE-p29"
+BRANCH="RELEASE-p30"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi
 RELEASE="${REVISION}-${BRANCH}"
 VERSION="${TYPE} ${RELEASE}"
 SYSDIR=$(dirname $0)/..
 
 if [ "X${PARAMFILE}" != "X" ]; then
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${PARAMFILE})
 else
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${SYSDIR}/sys/param.h)
 fi
 
 b=share/examples/etc/bsd-style-copyright
 year=`date '+%Y'`
 # look for copyright template
 for bsd_copyright in ../$b ../../$b ../../../$b /usr/src/$b /usr/$b
 do
 	if [ -r "$bsd_copyright" ]; then
 		COPYRIGHT=`sed \
 		    -e "s/\[year\]/1992-$year/" \
 		    -e 's/\[your name here\]\.* /The FreeBSD Project./' \
 		    -e 's/\[your name\]\.*/The FreeBSD Project./' \
 		    -e '/\[id for your version control system, if any\]/d' \
 		    $bsd_copyright` 
 		break
 	fi
 done
 
 # no copyright found, use a dummy
 if [ X"$COPYRIGHT" = X ]; then
 	COPYRIGHT="/*-
  * Copyright (c) 1992-$year The FreeBSD Project.
  * All rights reserved.
  *
  */"
 fi
 
 # add newline
 COPYRIGHT="$COPYRIGHT
 "
 
 LC_ALL=C; export LC_ALL
 if [ ! -r version ]
 then
 	echo 0 > version
 fi
 
 touch version
 v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
 i=`${MAKE:-make} -V KERN_IDENT`
 compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
 
 for dir in /bin /usr/bin /usr/local/bin; do
 	if [ -x "${dir}/svnversion" ] ; then
 		svnversion=${dir}/svnversion
 		break
 	fi
 done
 if [ -d "${SYSDIR}/../.git" ] ; then
 	for dir in /bin /usr/bin /usr/local/bin; do
 		if [ -x "${dir}/git" ] ; then
 			git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git"
 			break
 		fi
 	done
 fi
 
 if [ -n "$svnversion" ] ; then
 	echo "$svnversion"
 	svn=`cd ${SYSDIR} && $svnversion`
 	case "$svn" in
 	[0-9]*)	svn=" r${svn}" ;;
 	*)	unset svn ;;
 	esac
 fi
 
 if [ -n "$git_cmd" ] ; then
 	git=`$git_cmd rev-parse --verify --short HEAD 2>/dev/null`
 	svn=`$git_cmd svn find-rev $git 2>/dev/null`
 	if [ -n "$svn" ] ; then
 		svn=" r${svn}"
 		git="=${git}"
 	else
 		svn=`$git_cmd log | fgrep 'git-svn-id:' | head -1 | \
 		     sed -n 's/^.*@\([0-9][0-9]*\).*$/\1/p'`
 		if [ -n $svn ] ; then
 			svn=" r${svn}"
 			git="+${git}"
 		else
 			git=" ${git}"
 		fi
 	fi
 	if $git_cmd --work-tree=${SYSDIR}/.. diff-index \
 	    --name-only HEAD | read dummy; then
 		git="${git}-dirty"
 	fi
 fi
 
 cat << EOF > vers.c
 $COPYRIGHT
 #define SCCSSTR "@(#)${VERSION} #${v}${svn}${git}: ${t}"
 #define VERSTR "${VERSION} #${v}${svn}${git}: ${t}\\n    ${u}@${h}:${d}\\n"
 #define RELSTR "${RELEASE}"
 
 char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR;
 char version[sizeof(VERSTR) > 256 ? sizeof(VERSTR) : 256] = VERSTR;
 char compiler_version[] = "${compiler_v}";
 char ostype[] = "${TYPE}";
 char osrelease[sizeof(RELSTR) > 32 ? sizeof(RELSTR) : 32] = RELSTR;
 int osreldate = ${RELDATE};
 char kern_ident[] = "${i}";
 EOF
 
 echo $((v + 1)) > version
Index: releng/9.3/UPDATING
===================================================================
--- releng/9.3/UPDATING	(revision 284294)
+++ releng/9.3/UPDATING	(revision 284295)
@@ -1,1792 +1,1795 @@
 Updating Information for FreeBSD current users
 
 This file is maintained and copyrighted by M. Warner Losh .
 See end of file for further details.  For commonly done items, please see the
 COMMON ITEMS: section later in the file.  These instructions assume that you
 basically know what you are doing.  If not, then please consult the FreeBSD
 handbook:
 
     http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
 
 Items affecting the ports and packages system can be found in
 /usr/ports/UPDATING.  Please read that file before running portupgrade.
 
+20150612:	p16	FreeBSD-SA-15:10.openssl
+	Fix multiple vulnerabilities in OpenSSL.  [SA-15:10]
+
 20150609:	p15	FreeBSD-EN-15:06.file
 
 	Updated base system file(1) to 5.22 to address multiple denial
 	of service issues.
 
 20150513:	p14	FreeBSD-EN-15:04.freebsd-update
 
 	Fix bug with freebsd-update(8) that does not ensure the previous
 	upgrade was completed. [EN-15:04]
 
 20150407:	p13	FreeBSD-SA-15:04.igmp [revised]
 			FreeBSD-SA-15:07.ntp
 			FreeBSD-SA-15:09.ipv6
 
 	Improved patch for SA-15:04.igmp.
 
 	Fix multiple vulnerabilities of ntp. [SA-15:07]
 
 	Fix Denial of Service with IPv6 Router Advertisements. [SA-15:09]
 
 20150320:	p12
 	Fix patch for SA-15:06.openssl.
 
 20150319:	p11	FreeBSD-SA-15:06.openssl
 	Fix multiple vulnerabilities in OpenSSL.  [SA-15:06]
 
 20150225:	p10	FreeBSD-SA-15:04.igmp
 			FreeBSD-SA-15:05.bind
 			FreeBSD-EN-15:01.vt
 			FreeBSD-EN-15:02.openssl
 			FreeBSD-EN-15:03.freebsd-update
 
 	Fix integer overflow in IGMP protocol. [SA-15:04]
 
 	Fix BIND remote denial of service vulnerability. [SA-15:05]
 
 	Fix vt(4) crash with improper ioctl parameters. [EN-15:01]
 
 	Updated base system OpenSSL to 0.9.8zd. [EN-15:02]
 
 	Fix freebsd-update libraries update ordering issue. [EN-15:03]
 
 20150127:	p9	FreeBSD-SA-15:02.kmem
 			FreeBSD-SA-15:03.sctp
 
 	Fix SCTP SCTP_SS_VALUE kernel memory corruption and disclosure
 	vulnerability.  [SA-15:02]
 
 	Fix SCTP stream reset vulnerability.  [SA-15:03]
 
 20150114:	p8	FreeBSD-SA-15:01.openssl
 	Fix multiple vulnerabilities in OpenSSL.  [SA-15:01]
 
 20141223:	p7	FreeBSD-SA-14:31.ntp
 			FreeBSD-EN-14:13.freebsd-update
 
 	Fix multiple vulnerabilities in NTP suite.  [SA-14:31]
 	Fix directory deletion issue in freebsd-update.	 [EN-14:13]
 
 20141210:	p6	FreeBSD-SA-14:28.file
 			FreeBSD-SA-14:29.bind
 
 	Fix multiple vulnerabilities in file(1) and libmagic(3).
 	[SA-14:28]
 
 	Fix BIND remote denial of service vulnerability. [SA-14:29]
 
 20141104:	p5	FreeBSD-SA-14:25.setlogin
 			FreeBSD-SA-14:26.ftp
 			FreeBSD-EN-14:12.zfs
 
 	Fix kernel stack disclosure in setlogin(2) / getlogin(2).
 	[SA-14:25]
 
 	Fix remote command execution in ftp(1). [SA-14:26]
 
 	Fix NFSv4 and ZFS cache consistency issue. [EN-14:12]
 
 20141022:	p4	FreeBSD-EN-14:10.tzdata
 			FreeBSD-EN-14:11.crypt
 
 	Time zone data file update. [EN-14:10]
 
 	Change crypt(3) default hashing algorithm back to DES. [EN-14:11]
 
 20141021:	p3	FreeBSD-SA-14:20.rtsold
 			FreeBSD-SA-14:21.routed
 			FreeBSD-SA-14:22.namei
 			FreeBSD-SA-14:23.openssl
 
 	Fix rtsold(8) remote buffer overflow vulnerability. [SA-14:20]
 
 	Fix routed(8) remote denial of service vulnerability. [SA-14:21]
 
 	Fix memory leak in sandboxed namei lookup. [SA-14:22]
 
 	Fix OpenSSL multiple vulnerabilities. [SA-14:23]
 
 20140916:	p2	FreeBSD-SA-14:19.tcp
 	Fix Denial of Service in TCP packet processing. [SA-14:19]
 
 20140909:	p1	FreeBSD-SA-14:18.openssl
 	Fix OpenSSL multiple vulnerabilities. [SA-14:18]
 
 20140716:
 	9.3-RELEASE.
 
 20140608:
 	On i386 and amd64 systems, the onifconsole flag is now set by default
 	in /etc/ttys for ttyu0. This causes ttyu0 to be automatically enabled
 	as a login TTY if it is set in the bootloader as an active kernel
 	console. No changes in behavior should result otherwise. To revert to
 	the previous behavior, set ttyu0 to "off" in /etc/ttys.
 
 20140512:
 	Clang and llvm have been upgraded to 3.4.1 release.
 
 20140321:
 	Clang and llvm have been upgraded to 3.4 release.
 
 20140216:
 	The nve(4) driver for NVIDIA nForce MCP Ethernet adapters has
 	been deprecated and will not be part of FreeBSD 11.0 and later
 	releases.  If you use this driver, please consider switching to
 	the nfe(4) driver instead.
 
 20131216:
 	The behavior of gss_pseudo_random() for the krb5 mechanism
 	has changed, for applications requesting a longer random string
 	than produced by the underlying enctype's pseudo-random() function.
 	In particular, the random string produced from a session key of
 	enctype aes256-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96 will
 	be different at the 17th octet and later, after this change.
 	The counter used in the PRF+ construction is now encoded as a
 	big-endian integer in accordance with RFC 4402.
 	__FreeBSD_version is bumped to 902505.
 
 20130930:
 	9.2-RELEASE.
 
 20130823:
 	Behavior of devfs rules path matching has been changed.
 	Pattern is now always matched against fully qualified devfs
 	path and slash characters must be explicitly matched by
 	slashes in pattern (FNM_PATHNAME). Rulesets involving devfs
 	subdirectories must be reviewed.
 
 20130705:
 	hastctl(8)'s `status' command output changed to terse one-liner format.
 	Scripts using this should switch to `list' command or be rewritten.
 
 20130618:
         Fix a bug that allowed a tracing process (e.g. gdb) to write
         to a memory-mapped file in the traced process's address space
         even if neither the traced process nor the tracing process had
         write access to that file.
 
 20130605:
 	Added ZFS TRIM support which is enabled by default. To disable
 	ZFS TRIM support set vfs.zfs.trim.enabled=0 in loader.conf.
 
 	Creating new ZFS pools and adding new devices to existing pools
 	first performs a full device level TRIM which can take a significant
 	amount of time. The sysctl vfs.zfs.vdev.trim_on_init can be set to 0
 	to disable this behaviour.
 
 	ZFS TRIM requires the underlying device support BIO_DELETE which
 	is currently provided by methods such as ATA TRIM and SCSI UNMAP
 	via CAM, which are typically supported by SSD's.
 
 	Stats for ZFS TRIM can be monitored by looking at the sysctl's
 	under kstat.zfs.misc.zio_trim.
 
 20130524:
 	`list' command has been added to hastctl(8).  For now, it is full
 	equivalent of `status' command.
 	WARNING: in the near future the output of hastctl's status command
 	will change to more terse format.  If you use `hastctl status'
 	for parsing in your scripts, switch to `hastctl list'.
 
 20130430:
 	The mergemaster command now uses the default MAKEOBJDIRPREFIX
 	rather than creating it's own in the temporary directory in
 	order allow access to bootstrapped versions of tools such as
 	install and mtree.  When upgrading from version of FreeBSD where
 	the install command does not support -l, you will need to
 	install a new mergemaster command if mergemaster -p is required.
 	This can be accomplished with the command (cd src/usr.sbin/mergemaster
 	&& make install).
 
 	Due to the use of the new -l option to install(1) during build
 	and install, you must take care not to directly set the INSTALL
 	make variable in your /etc/make.conf, /etc/src.conf, or on the
 	command line.  If you wish to use the -C flag for all installs
 	you may be able to add INSTALL+=-C to /etc/make.conf or
 	/etc/src.conf.
 
 20130429:
 	Fix a bug that allows NFS clients to issue READDIR on files.
 
 20130315:
 	The install(1) option -M has changed meaning and now takes an
 	argument that is a file or path to append logs to.  In the
 	unlikely event that -M was the last option on the command line
 	and the command line contained at least two files and a target
 	directory the first file will have logs appended to it.  The -M
 	option served little practical purpose in the last decade so it's
 	used expected to be extremely rare.
 
 20130225:
 	A new compression method (lz4) has been merged to.  Please refer to
 	zpool-features(7) for more information.
 
 	Please refer to the "ZFS notes" section of this file for information
 	on upgrading boot ZFS pools.
 
 20121224:
 	The VFS KBI was changed with the merge of several nullfs
 	optimizations and fixes.  All filesystem modules must be
 	recompiled.
 
 20121218:
 	With the addition of auditdistd(8), a new auditdistd user is now
 	depended on during installworld.  "mergemaster -p" can be used to add
 	the user prior to installworld, as documented in the handbook.
 
 20121205:
 	9.1-RELEASE.
 
 20121129:
 	A new version of ZFS (pool version 5000) has been merged to 9-STABLE.
 	Starting with this version the old system of ZFS pool versioning
 	is superseded by "feature flags". This concept enables forward
 	compatibility against certain future changes in functionality of ZFS
 	pools. The first two read-only compatible "feature flags" for ZFS
 	pools are "com.delphix:async_destroy" and "com.delphix:empty_bpobj".
 	For more information read the new zpool-features(7) manual page.
 	Please refer to the "ZFS notes" section of this file for information
 	on upgrading boot ZFS pools.
 
 20121114:
 	The commit introducing bsd.compiler.mk breaks the traditional
 	building of kernels before this point. Add -m ${SRC}/share/mk
 	(for the right value of SRC) to your command lines to work
 	around; update your useland to a point after this; or use the
 	buildkernel/installkernel top-level targets. See also 20120829.
 
 20121102:
 	The IPFIREWALL_FORWARD kernel option has been removed. Its
 	functionality now turned on by default.
 
 20120913:
 	The random(4) support for the VIA hardware random number
 	generator (`PADLOCK') is no longer enabled unconditionally.
 	Add the PADLOCK_RNG option in the custom kernel config if
 	needed.  The GENERIC kernels on i386 and amd64 do include the
 	option, so the change only affects the custom kernel
 	configurations.
 
 20120829:
 	The amd64 kernel now uses xsetbv, xrstor instructions. To compile with
 	the traditional method, you must update your system with an installworld
 	before the kernel will build. The documented make buildkernel/installkernel
 	interfaces (coupled with fresh make kernel-toolchain) continue to work.
 
 20120727:
 	The sparc64 ZFS loader has been changed to no longer try to auto-
 	detect ZFS providers based on diskN aliases but now requires these
 	to be explicitly listed in the OFW boot-device environment variable.
 
 20120422:
 	Now unix domain sockets behave "as expected" on	nullfs(5). Previously
 	nullfs(5) did not pass through all behaviours to the underlying layer,
 	as a result if we bound to a socket on the lower layer we could connect
 	only to the lower path; if we bound to the upper layer we could connect
 	only to	the upper path. The new behavior is one can connect to both the
 	lower and the upper paths regardless what layer path one binds to.
 
 20120109:
 	The acpi_wmi(4) status device /dev/wmistat has been renamed to
 	/dev/wmistat0.
 
 20120106:
 	A new VOP_ADVISE() was added to support posix_fadvise(2).  All
 	filesystem modules must be recompiled.
 
 20120106:
 	The interface of the VOP_VPTOCNP(9) changed, now the returned
 	vnode shall be referenced, previously it was required to be
 	only held.  All in-tree filesystems are converted.
 
 20120106:
 	9.0-RELEASE.
 
 20111101:
 	The broken amd(4) driver has been replaced with esp(4) in the amd64,
 	i386 and pc98 GENERIC kernel configuration files.
 
 20110913:
 	This commit modifies vfs_register() so that it uses a hash
 	calculation to set vfc_typenum, which is enabled by default.
 	The first time a system is booted after this change, the
 	vfc_typenum values will change for all file systems. The
 	main effect of this is a change to the NFS server file handles
 	for file systems that use vfc_typenum in their fsid, such as ZFS.
 	It will, however, prevent vfc_typenum from changing when file
 	systems are loaded in a different order for subsequent reboots.
 	To disable this, you can set vfs.typenumhash=0 in /boot/loader.conf
 	until you are ready to remount all NFS clients after a reboot.
 
 20110828:
 	Bump the shared library version numbers for libraries that
 	do not use symbol versioning, have changed the ABI compared
 	to stable/8 and which shared library version was not bumped.
 	Done as part of 9.0-RELEASE cycle.
 
 20110815:
 	During the merge of Capsicum features, the fget(9) KPI was modified.
 	This may require the rebuilding of out-of-tree device drivers --
 	issues have been reported specifically with the nVidia device driver.
 	__FreeBSD_version is bumped to 900041.
 
 	Also, there is a period between 20110811 and 20110814 where the
 	special devices /dev/{stdin,stdout,stderr} did not work correctly.
 	Building world from a kernel during that window may not work.
 
 20110628:
 	The packet filter (pf) code has been updated to OpenBSD 4.5.
 	You need to update userland tools to be in sync with kernel.
 	This update breaks backward compatibility with earlier pfsync(4)
 	versions.  Care must be taken when updating redundant firewall setups.
 
 20110608:
 	The following sysctls and tunables are retired on x86 platforms:
 		machdep.hlt_cpus
 		machdep.hlt_logical_cpus
 	The following sysctl is retired:
 		machdep.hyperthreading_allowed
 	The sysctls were supposed to provide a way to dynamically offline and
 	online selected CPUs on x86 platforms, but the implementation has not
 	been reliable especially with SCHED_ULE scheduler.
 	machdep.hyperthreading_allowed tunable is still available to ignore
 	hyperthreading CPUs at OS level.
 	Individual CPUs can be disabled using hint.lapic.X.disabled tunable,
 	where X is an APIC ID of a CPU.  Be advised, though, that disabling
 	CPUs in non-uniform fashion will result in non-uniform topology and
 	may lead to sub-optimal system performance with SCHED_ULE, which is
 	a default scheduler.
 
 20110607:
 	cpumask_t type is retired and cpuset_t is used in order to describe
 	a mask of CPUs.
 
 20110531:
 	Changes to ifconfig(8) for dynamic address family detection mandate
 	that you are running a kernel of 20110525 or later.  Make sure to
 	follow the update procedure to boot a new kernel before installing
 	world.
 
 20110513:
 	Support for sun4v architecture is officially dropped
 
 20110503:
 	Several KPI breaking changes have been committed to the mii(4) layer,
 	the PHY drivers and consequently some Ethernet drivers using mii(4).
 	This means that miibus.ko and the modules of the affected Ethernet
 	drivers need to be recompiled.
 
 	Note to kernel developers: Given that the OUI bit reversion problem
 	was fixed as part of these changes all mii(4) commits related to OUIs,
 	i.e. to sys/dev/mii/miidevs, PHY driver probing and vendor specific
 	handling, no longer can be merged verbatim to stable/8 and previous
 	branches.
 
 20110430:
 	Users of the Atheros AR71xx SoC code now need to add 'device ar71xx_pci'
 	into their kernel configurations along with 'device pci'.
 
 20110427:
 	The default NFS client is now the new NFS client, so fstype "newnfs"
 	is now "nfs" and the regular/old NFS client is now fstype "oldnfs".
 	Although mounts via fstype "nfs" will usually work without userland
 	changes, it is recommended that the mount(8) and mount_nfs(8)
 	commands be rebuilt from sources and that a link to mount_nfs called
 	mount_oldnfs be created. The new client is compiled into the
 	kernel with "options NFSCL" and this is needed for diskless root
 	file systems. The GENERIC kernel configs have been changed to use
 	NFSCL and NFSD (the new server) instead of NFSCLIENT and NFSSERVER.
 	To use the regular/old client, you can "mount -t oldnfs ...". For
 	a diskless root file system, you must also include a line like:
 	
 	vfs.root.mountfrom="oldnfs:"
 
 	in the boot/loader.conf on the root fs on the NFS server to make
 	a diskless root fs use the old client.
 
 20110424:
 	The GENERIC kernels for all architectures now default to the new
 	CAM-based ATA stack. It means that all legacy ATA drivers were
 	removed and replaced by respective CAM drivers. If you are using
 	ATA device names in /etc/fstab or other places, make sure to update
 	them respectively (adX -> adaY, acdX -> cdY, afdX -> daY, astX -> saY,
 	where 'Y's are the sequential numbers starting from zero for each type
 	in order of detection, unless configured otherwise with tunables,
 	see cam(4)). There will be symbolic links created in /dev/ to map
 	old adX devices to the respective adaY. They should provide basic
 	compatibility for file systems mounting in most cases, but they do
 	not support old user-level APIs and do not have respective providers
 	in GEOM. Consider using updated management tools with new device names.
 
 	It is possible to load devices ahci, ata, siis and mvs as modules,
 	but option ATA_CAM should remain in kernel configuration to make ata
 	module work as CAM driver supporting legacy ATA controllers. Device ata
 	still can be used in modular fashion (atacore + ...). Modules atadisk
 	and atapi* are not used and won't affect operation in ATA_CAM mode.
 	Note that to use CAM-based ATA kernel should include CAM devices
 	scbus, pass, da (or explicitly ada), cd and optionally others. All of
 	them are parts of the cam module.
 
 	ataraid(4) functionality is now supported by the RAID GEOM class.
 	To use it you can load geom_raid kernel module and use graid(8) tool
 	for management. Instead of /dev/arX device names, use /dev/raid/rX.
 
 	No kernel config options or code have been removed, so if a problem
 	arises, please report it and optionally revert to the old ATA stack.
 	In order to do it you can remove from the kernel config:
 	    options        ATA_CAM
 	    device         ahci
 	    device         mvs
 	    device         siis
 	, and instead add back:
 	    device         atadisk         # ATA disk drives
 	    device         ataraid         # ATA RAID drives
 	    device         atapicd         # ATAPI CDROM drives
 	    device         atapifd         # ATAPI floppy drives
 	    device         atapist         # ATAPI tape drives
 
 20110423:
 	The default NFS server has been changed to the new server, which
 	was referred to as the experimental server. If you need to switch
 	back to the old NFS server, you must now put the "-o" option on
 	both the mountd and nfsd commands. This can be done using the
 	mountd_flags and nfs_server_flags rc.conf variables until an
 	update to the rc scripts is committed, which is coming soon.
 
 20110418:
 	The GNU Objective-C runtime library (libobjc), and other Objective-C
 	related components have been removed from the base system.  If you
 	require an Objective-C library, please use one of the available ports.
 
 20110331:
 	ath(4) has been split into bus- and device- modules. if_ath contains
 	the HAL, the TX rate control and the network device code. if_ath_pci
 	contains the PCI bus glue. For Atheros MIPS embedded systems, if_ath_ahb
 	contains the AHB glue. Users need to load both if_ath_pci and if_ath
 	in order to use ath on everything else.
 
 	TO REPEAT: if_ath_ahb is not needed for normal users. Normal users only
 	need to load if_ath and if_ath_pci for ath(4) operation.
 
 20110314:
 	As part of the replacement of sysinstall, the process of building
 	release media has changed significantly. For details, please re-read
 	release(7), which has been updated to reflect the new build process.
 
 20110218:
 	GNU binutils 2.17.50 (as of 2007-07-03) has been merged to -HEAD.  This
 	is the last available version under GPLv2.  It brings a number of new
 	features, such as support for newer x86 CPU's (with SSE-3, SSSE-3, SSE
 	4.1 and SSE 4.2), better support for powerpc64, a number of new
 	directives, and lots of other small improvements.  See the ChangeLog
 	file in contrib/binutils for the full details.
 
 20110218:
 	IPsec's HMAC_SHA256-512 support has been fixed to be RFC4868
 	compliant, and will now use half of hash for authentication.
 	This will break interoperability with all stacks (including all
 	actual FreeBSD versions) who implement
 	draft-ietf-ipsec-ciph-sha-256-00 (they use 96 bits of hash for
 	authentication).
 	The only workaround with such peers is to use another HMAC
 	algorithm for IPsec ("phase 2") authentication.
 
 20110207:
 	Remove the uio_yield prototype and symbol.  This function has
 	been misnamed since it was introduced and should not be
 	globally exposed with this name.  The equivalent functionality
 	is now available using kern_yield(curthread->td_user_pri).
 	The function remains undocumented.
 
 20110112:
 	A SYSCTL_[ADD_]UQUAD was added for unsigned uint64_t pointers,
 	symmetric with the existing SYSCTL_[ADD_]QUAD.  Type checking
 	for scalar sysctls is defined but disabled.  Code that needs
 	UQUAD to pass the type checking that must compile on older
 	systems where the define is not present can check against
 	__FreeBSD_version >= 900030.
 
 	The system dialog(1) has been replaced with a new version previously
 	in ports as devel/cdialog. dialog(1) is mostly command-line compatible
 	with the previous version, but the libdialog associated with it has
 	a largely incompatible API. As such, the original version of libdialog
 	will be kept temporarily as libodialog, until its base system consumers
 	are replaced or updated. Bump __FreeBSD_version to 900030.
 
 20110103:
 	If you are trying to run make universe on a -stable system, and you get
 	the following warning:
 	"Makefile", line 356: "Target architecture for i386/conf/GENERIC 
 	unknown.  config(8) likely too old."
 	or something similar to it, then you must upgrade your -stable system
 	to 8.2-Release or newer (really, any time after r210146 7/15/2010 in
 	stable/8) or build the config from the latest stable/8 branch and
 	install it on your system.
 
 	Prior to this date, building a current universe on 8-stable system from
 	between 7/15/2010 and 1/2/2011 would result in a weird shell parsing
 	error in the first kernel build phase.  A new config on those old 
 	systems will fix that problem for older versions of -current.
 
 20101228:
 	The TCP stack has been modified to allow Khelp modules to interact with
 	it via helper hook points and store per-connection data in the TCP
 	control block. Bump __FreeBSD_version to 900029. User space tools that
 	rely on the size of struct tcpcb in tcp_var.h (e.g. sockstat) need to
 	be recompiled.
 
 20101114:
 	Generic IEEE 802.3 annex 31B full duplex flow control support has been
 	added to mii(4) and bge(4), bce(4), msk(4), nfe(4) and stge(4) along
 	with brgphy(4), e1000phy(4) as well as ip1000phy() have been converted
 	to take advantage of it instead of using custom implementations.  This
 	means that these drivers now no longer unconditionally advertise
 	support for flow control but only do so if flow control is a selected
 	media option.  This was implemented in the generic support that way in
 	order to allow flow control to be switched on and off via ifconfig(8)
 	with the PHY specific default to typically off in order to protect
 	from unwanted effects.  Consequently, if you used flow control with
 	one of the above mentioned drivers you now need to explicitly enable
 	it, for example via:
 		ifconfig bge0 media auto mediaopt flowcontrol
 
 	Along with the above mentioned changes generic support for setting
 	1000baseT master mode also has been added and brgphy(4), ciphy(4),
 	e1000phy(4) as well as ip1000phy(4) have been converted to take
 	advantage of it.  This means that these drivers now no longer take the
 	link0 parameter for selecting master mode but the master media option
 	has to be used instead, for example like in the following:
 		ifconfig bge0 media 1000baseT mediaopt full-duplex,master
 
 	Selection of master mode now is also available with all other PHY
 	drivers supporting 1000baseT.
 
 20101111:
 	The TCP stack has received a significant update to add support for
 	modularised congestion control and generally improve the clarity of
 	congestion control decisions. Bump __FreeBSD_version to 900025. User
 	space tools that rely on the size of struct tcpcb in tcp_var.h (e.g.
 	sockstat) need to be recompiled.
 
 20101002:
 	The man(1) utility has been replaced by a new version that no longer
 	uses /etc/manpath.config. Please consult man.conf(5) for how to
 	migrate local entries to the new format.
 
 20100928:
 	The copyright strings printed by login(1) and sshd(8) at the time of a
 	new connection have been removed to follow other operating systems and
 	upstream sshd.
 
 20100915:
 	A workaround for a fixed ld bug has been removed in kernel code,
 	so make sure that your system ld is built from sources after
 	revision 210245 from 2010-07-19 (r211583 if building head kernel
 	on stable/8, r211584 for stable/7; both from 2010-08-21).
 	A symptom of incorrect ld version is different addresses for
 	set_pcpu section and __start_set_pcpu symbol in kernel and/or modules.
 
 20100913:
 	The $ipv6_prefer variable in rc.conf(5) has been split into
 	$ip6addrctl_policy and $ipv6_activate_all_interfaces.
 
 	The $ip6addrctl_policy is a variable to choose a pre-defined
 	address selection policy set by ip6addrctl(8).  A value
 	"ipv4_prefer", "ipv6_prefer" or "AUTO" can be specified.  The
 	default is "AUTO".
 
 	The $ipv6_activate_all_interfaces specifies whether IFDISABLED
 	flag (see an entry of 20090926) is set on an interface with no
 	corresponding $ifconfig_IF_ipv6 line.  The default is "NO" for
 	security reason.  If you want IPv6 link-local address on all
 	interfaces by default, set this to "YES".
 
 	The old ipv6_prefer="YES" is equivalent to
 	ipv6_activate_all_interfaces="YES" and
 	ip6addrctl_policy="ipv6_prefer".
 
 20100913:
 	DTrace has grown support for userland tracing. Due to this, DTrace is
 	now i386 and amd64 only.
 	dtruss(1) is now installed by default on those systems and a new
 	kernel module is needed for userland tracing: fasttrap.
 	No changes to your kernel config file are necessary to enable
 	userland tracing, but you might consider adding 'STRIP=' and
 	'CFLAGS+=-fno-omit-frame-pointer' to your make.conf if you want
 	to have informative userland stack traces in DTrace (ustack).
 
 20100725:
 	The acpi_aiboost(4) driver has been removed in favor of the new
 	aibs(4) driver. You should update your kernel configuration file.
 
 20100722:
 	BSD grep has been imported to the base system and it is built by
 	default.  It is completely BSD licensed, highly GNU-compatible, uses
 	less memory than its GNU counterpart and has a small codebase.
 	However, it is slower than its GNU counterpart, which is mostly
 	noticeable for larger searches, for smaller ones it is measurable
 	but not significant.  The reason is complex, the most important factor
 	is that we lack a modern and efficient regex library and GNU
 	overcomes this by optimizing the searches internally.  Future work
 	on improving the regex performance is planned, for the meantime,
 	users that need better performance, can build GNU grep instead by
 	setting the WITH_GNU_GREP knob.
 
 20100713:
 	Due to the import of powerpc64 support, all existing powerpc kernel
 	configuration files must be updated with a machine directive like this:
 	    machine powerpc powerpc
 
 	In addition, an updated config(8) is required to build powerpc kernels
 	after this change.
 
 20100713:
 	A new version of ZFS (version 15) has been merged to -HEAD.
 	This version uses a python library for the following subcommands:
 	zfs allow, zfs unallow, zfs groupspace, zfs userspace.
 	For full functionality of these commands the following port must
 	be installed: sysutils/py-zfs
 
 20100429:
 	'vm_page's are now hashed by physical address to an array of mutexes.
 	Currently this is only used to serialize access to hold_count. Over 
 	time the page queue mutex will be peeled away. This changes the size
 	of pmap on every architecture. And requires all callers of vm_page_hold
 	and vm_page_unhold to be updated. 
  
 20100402:
 	WITH_CTF can now be specified in src.conf (not recommended, there
 	are some problems with static executables), make.conf (would also
 	affect ports which do not use GNU make and do not override the
 	compile targets) or in the kernel config (via "makeoptions
 	WITH_CTF=yes").
 	When WITH_CTF was specified there before this was silently ignored,
 	so make sure that WITH_CTF is not used in places which could lead
 	to unwanted behavior.
 
 20100311:
 	The kernel option COMPAT_IA32 has been replaced with COMPAT_FREEBSD32
 	to allow 32-bit compatibility on non-x86 platforms. All kernel
 	configurations on amd64 and ia64 platforms using these options must
 	be modified accordingly.
 
 20100113:
 	The utmp user accounting database has been replaced with utmpx,
 	the user accounting interface standardized by POSIX.
 	Unfortunately the semantics of utmp and utmpx don't match,
 	making it practically impossible to support both interfaces.
 	The user accounting database is used by tools like finger(1),
 	last(1), talk(1), w(1) and ac(8).
 
 	All applications in the base system use utmpx.  This means only
 	local binaries (e.g. from the ports tree) may still use these
 	utmp database files.  These applications must be rebuilt to make
 	use of utmpx.
 
 	After the system has been upgraded, it is safe to remove the old
 	log files (/var/run/utmp, /var/log/lastlog and /var/log/wtmp*),
 	assuming their contents is of no importance anymore.  Old wtmp
 	databases can only be used by last(1) and ac(8) after they have
 	been converted to the new format using wtmpcvt(1).
 
 20100108:
 	Introduce the kernel thread "deadlock resolver" (which can be enabled
 	via the DEADLKRES option, see NOTES for more details) and the
 	sleepq_type() function for sleepqueues.
 
 20091202:
 	The rc.firewall and rc.firewall6 were unified, and
 	rc.firewall6 and rc.d/ip6fw were removed.
 	According to the removal of rc.d/ip6fw, ipv6_firewall_* rc
 	variables are obsoleted.  Instead, the following new rc
 	variables are added to rc.d/ipfw:
 
 		firewall_client_net_ipv6, firewall_simple_iif_ipv6,
 		firewall_simple_inet_ipv6, firewall_simple_oif_ipv6,
 		firewall_simple_onet_ipv6, firewall_trusted_ipv6
 
 	The meanings correspond to the relevant IPv4 variables.
 
 20091125:
 	8.0-RELEASE.
 
 20091113:
 	The default terminal emulation for syscons(4) has been changed
 	from cons25 to xterm on all platforms except pc98.  This means
 	that the /etc/ttys file needs to be updated to ensure correct
 	operation of applications on the console.
 
 	The terminal emulation style can be toggled per window by using
 	vidcontrol(1)'s -T flag.  The TEKEN_CONS25 kernel configuration
 	options can be used to change the compile-time default back to
 	cons25.
 
 	To prevent graphical artifacts, make sure the TERM environment
 	variable is set to match the terminal emulation that is being
 	performed by syscons(4).
 
 20091109:
 	The layout of the structure ieee80211req_scan_result has changed.
 	Applications that require wireless scan results (e.g. ifconfig(8))
 	from net80211 need to be recompiled.
 
 	Applications such as wpa_supplicant(8) may require a full world
 	build without using NO_CLEAN in order to get synchronized with the
 	new structure.
 
 20091025:
 	The iwn(4) driver has been updated to support the 5000 and 5150 series.
 	There's one kernel module for each firmware. Adding "device iwnfw"
 	to the kernel configuration file means including all three firmware
 	images inside the kernel. If you want to include just the one for
 	your wireless card, use the devices iwn4965fw, iwn5000fw or
 	iwn5150fw.
 
 20090926:
 	The rc.d/network_ipv6, IPv6 configuration script has been integrated
 	into rc.d/netif.  The changes are the following:
 
 	1. To use IPv6, simply define $ifconfig_IF_ipv6 like $ifconfig_IF
 	   for IPv4.  For aliases, $ifconfig_IF_aliasN should be used.
 	   Note that both variables need the "inet6" keyword at the head.
 
 	   Do not set $ipv6_network_interfaces manually if you do not
 	   understand what you are doing.  It is not needed in most cases. 
 
 	   $ipv6_ifconfig_IF and $ipv6_ifconfig_IF_aliasN still work, but
 	   they are obsolete.
 
 	2. $ipv6_enable is obsolete.  Use $ipv6_prefer and
 	   "inet6 accept_rtadv" keyword in ifconfig(8) instead.
 
 	   If you define $ipv6_enable=YES, it means $ipv6_prefer=YES and
 	   all configured interfaces have "inet6 accept_rtadv" in the
 	   $ifconfig_IF_ipv6.  These are for backward compatibility.
 
 	3. A new variable $ipv6_prefer has been added.  If NO, IPv6
 	   functionality of interfaces with no corresponding
 	   $ifconfig_IF_ipv6 is disabled by using "inet6 ifdisabled" flag,
 	   and the default address selection policy of ip6addrctl(8) 
 	   is the IPv4-preferred one (see rc.d/ip6addrctl for more details).
 	   Note that if you want to configure IPv6 functionality on the
 	   disabled interfaces after boot, first you need to clear the flag by
 	   using ifconfig(8) like:
 
 		ifconfig em0 inet6 -ifdisabled
 
 	   If YES, the default address selection policy is set as
 	   IPv6-preferred.
 
 	   The default value of $ipv6_prefer is NO.
 
 	4. If your system need to receive Router Advertisement messages,
 	   define "inet6 accept_rtadv" in $ifconfig_IF_ipv6.  The rc(8)
 	   scripts automatically invoke rtsol(8) when the interface becomes
 	   UP.  The Router Advertisement messages are used for SLAAC
 	   (State-Less Address AutoConfiguration).
 
 20090922:
 	802.11s D3.03 support was committed. This is incompatible with the
 	previous code, which was based on D3.0.
 
 20090912:
 	A sysctl variable net.inet6.ip6.accept_rtadv now sets the default value
 	of a per-interface flag ND6_IFF_ACCEPT_RTADV, not a global knob to
 	control whether accepting Router Advertisement messages or not.
 	Also, a per-interface flag ND6_IFF_AUTO_LINKLOCAL has been added and
 	a sysctl variable net.inet6.ip6.auto_linklocal is its default value.
 	The ifconfig(8) utility now supports these flags.
 
 20090910:
 	ZFS snapshots are now mounted with MNT_IGNORE flag. Use -v option for
 	mount(8) and -a option for df(1) to see them.
 
 20090825:
 	The old tunable hw.bus.devctl_disable has been superseded by
 	hw.bus.devctl_queue.  hw.bus.devctl_disable=1 in loader.conf should be
 	replaced by hw.bus.devctl_queue=0.  The default for this new tunable
 	is 1000.
 
 20090813:
 	Remove the option STOP_NMI.  The default action is now to use NMI only
 	for KDB via the newly introduced function stop_cpus_hard() and
 	maintain stop_cpus() to just use a normal IPI_STOP on ia32 and amd64.
 
 20090803:
 	The stable/8 branch created in subversion.  This corresponds to the
 	RELENG_8 branch in CVS.
 
 20090719:
 	Bump the shared library version numbers for all libraries that do not
 	use symbol versioning as part of the 8.0-RELEASE cycle.  Bump
 	__FreeBSD_version to 800105.
 
 20090714:
 	Due to changes in the implementation of virtual network stack support,
 	all network-related kernel modules must be recompiled.  As this change
 	breaks the ABI, bump __FreeBSD_version to 800104.
 
 20090713:
 	The TOE interface to the TCP syncache has been modified to remove
 	struct tcpopt () from the ABI of the network stack.
 	The cxgb driver is the only TOE consumer affected by this change, and
 	needs to be recompiled along with the kernel. As this change breaks
 	the ABI, bump __FreeBSD_version to 800103.
 
 20090712: 
 	Padding has been added to struct tcpcb, sackhint and tcpstat in
 	 to facilitate future MFCs and bug fixes whilst
 	maintaining the ABI. However, this change breaks the ABI, so bump
 	__FreeBSD_version to 800102. User space tools that rely on the size of
 	any of these structs (e.g. sockstat) need to be recompiled.
 
 20090630:
 	The NFS_LEGACYRPC option has been removed along with the old kernel
 	RPC implementation that this option selected. Kernel configurations
 	may need to be adjusted.
 
 20090629:
 	The network interface device nodes at /dev/net/ have been
 	removed.  All ioctl operations can be performed the normal way using
 	routing sockets.  The kqueue functionality can generally be replaced
 	with routing sockets.
 
 20090628:
 	The documentation from the FreeBSD Documentation Project (Handbook,
 	FAQ, etc.) is now installed via packages by sysinstall(8) and under
 	the /usr/local/share/doc/freebsd directory instead of /usr/share/doc.
 
 20090624:
 	The ABI of various structures related to the SYSV IPC API have been
 	changed.  As a result, the COMPAT_FREEBSD[456] and COMPAT_43 kernel
 	options now all require COMPAT_FREEBSD7.  Bump __FreeBSD_version to
 	800100.
 
 20090622:
 	Layout of struct vnet has changed as routing related variables were
 	moved to their own Vimage module. Modules need to be recompiled.  Bump
 	__FreeBSD_version to 800099.
 
 20090619:
 	NGROUPS_MAX and NGROUPS have been increased from 16 to 1023 and 1024
 	respectively.  As long as no more than 16 groups per process are used,
 	no changes should be visible.  When more than 16 groups are used, old
 	binaries may fail if they call getgroups() or getgrouplist() with
 	statically sized storage.  Recompiling will work around this, but
 	applications should be modified to use dynamically allocated storage
 	for group arrays as POSIX.1-2008 does not cap an implementation's
 	number of supported groups at NGROUPS_MAX+1 as previous versions did.
 
 	NFS and portalfs mounts may also be affected as the list of groups is
 	truncated to 16.  Users of NFS who use more than 16 groups, should
 	take care that negative group permissions are not used on the exported
 	file systems as they will not be reliable unless a GSSAPI based
 	authentication method is used.
 
 20090616: 
 	The compiling option ADAPTIVE_LOCKMGRS has been introduced.  This
 	option compiles in the support for adaptive spinning for lockmgrs
 	which want to enable it.  The lockinit() function now accepts the flag
 	LK_ADAPTIVE in order to make the lock object subject to adaptive
 	spinning when both held in write and read mode.
 
 20090613:
 	The layout of the structure returned by IEEE80211_IOC_STA_INFO has
 	changed.  User applications that use this ioctl need to be rebuilt.
 
 20090611:
 	The layout of struct thread has changed.  Kernel and modules need to
 	be rebuilt.
 
 20090608:
 	The layout of structs ifnet, domain, protosw and vnet_net has changed.
 	Kernel modules need to be rebuilt.  Bump __FreeBSD_version to 800097.
 
 20090602:
 	window(1) has been removed from the base system. It can now be
 	installed from ports. The port is called misc/window.
 
 20090601:
 	The way we are storing and accessing `routing table' entries has
 	changed. Programs reading the FIB, like netstat, need to be
 	re-compiled.
 
 20090601:
 	A new netisr implementation has been added for FreeBSD 8.  Network
 	file system modules, such as igmp, ipdivert, and others, should be
 	rebuilt.
 	Bump __FreeBSD_version to 800096.
 
 20090530:
 	Remove the tunable/sysctl debug.mpsafevfs as its initial purpose is no
 	more valid.
 
 20090530:
 	Add VOP_ACCESSX(9).  File system modules need to be rebuilt.
 	Bump __FreeBSD_version to 800094.
 
 20090529:
 	Add mnt_xflag field to 'struct mount'.  File system modules need to be
 	rebuilt.
 	Bump __FreeBSD_version to 800093.
 
 20090528:
 	The compiling option ADAPTIVE_SX has been retired while it has been
 	introduced the option NO_ADAPTIVE_SX which handles the reversed logic.
 	The KPI for sx_init_flags() changes as accepting flags:
 	SX_ADAPTIVESPIN flag has been retired while the SX_NOADAPTIVE flag has
 	been introduced in order to handle the reversed logic.
 	Bump __FreeBSD_version to 800092.
 
 20090527:
 	Add support for hierarchical jails.  Remove global securelevel.
 	Bump __FreeBSD_version to 800091.
 
 20090523:
 	The layout of struct vnet_net has changed, therefore modules
 	need to be rebuilt.
 	Bump __FreeBSD_version to 800090.
 
 20090523:
 	The newly imported zic(8) produces a new format in the output. Please
 	run tzsetup(8) to install the newly created data to /etc/localtime.
 
 20090520:
 	The sysctl tree for the usb stack has renamed from hw.usb2.* to
 	hw.usb.* and is now consistent again with previous releases.
 
 20090520:
 	802.11 monitor mode support was revised and driver api's were changed.
 	Drivers dependent on net80211 now support DLT_IEEE802_11_RADIO instead
 	of DLT_IEEE802_11.  No user-visible data structures were changed but
 	applications that use DLT_IEEE802_11 may require changes.
 	Bump __FreeBSD_version to 800088.
 
 20090430:
 	The layout of the following structs has changed: sysctl_oid,
 	socket, ifnet, inpcbinfo, tcpcb, syncache_head, vnet_inet,
 	vnet_inet6 and vnet_ipfw.  Most modules need to be rebuild or
 	panics may be experienced.  World rebuild is required for
 	correctly checking networking state from userland.
 	Bump __FreeBSD_version to 800085.
 
 20090429:
 	MLDv2 and Source-Specific Multicast (SSM) have been merged
 	to the IPv6 stack. VIMAGE hooks are in but not yet used.
 	The implementation of SSM within FreeBSD's IPv6 stack closely
 	follows the IPv4 implementation.
 
 	For kernel developers:
 
 	* The most important changes are that the ip6_output() and
 	  ip6_input() paths no longer take the IN6_MULTI_LOCK,
 	  and this lock has been downgraded to a non-recursive mutex.
 
 	* As with the changes to the IPv4 stack to support SSM, filtering
 	  of inbound multicast traffic must now be performed by transport
 	  protocols within the IPv6 stack. This does not apply to TCP and
 	  SCTP, however, it does apply to UDP in IPv6 and raw IPv6.
 
 	* The KPIs used by IPv6 multicast are similar to those used by
 	  the IPv4 stack, with the following differences:
 	   * im6o_mc_filter() is analogous to imo_multicast_filter().
 	   * The legacy KAME entry points in6_joingroup and in6_leavegroup()
 	     are shimmed to in6_mc_join() and in6_mc_leave() respectively.
 	   * IN6_LOOKUP_MULTI() has been deprecated and removed.
 	   * IPv6 relies on MLD for the DAD mechanism. KAME's internal KPIs
 	     for MLDv1 have an additional 'timer' argument which is used to
 	     jitter the initial membership report for the solicited-node
 	     multicast membership on-link.
 	   * This is not strictly needed for MLDv2, which already jitters
 	     its report transmissions.  However, the 'timer' argument is
 	     preserved in case MLDv1 is active on the interface.
 
 	* The KAME linked-list based IPv6 membership implementation has
 	  been refactored to use a vector similar to that used by the IPv4
 	  stack.
 	  Code which maintains a list of its own multicast memberships
 	  internally, e.g. carp, has been updated to reflect the new
 	  semantics.
 
 	* There is a known Lock Order Reversal (LOR) due to in6_setscope()
 	  acquiring the IF_AFDATA_LOCK and being called within ip6_output().
 	  Whilst MLDv2 tries to avoid this otherwise benign LOR, it is an
 	  implementation constraint which needs to be addressed in HEAD.
 
 	For application developers:
 
 	* The changes are broadly similar to those made for the IPv4
 	  stack.
 
 	* The use of IPv4 and IPv6 multicast socket options on the same
 	  socket, using mapped addresses, HAS NOT been tested or supported.
 
 	* There are a number of issues with the implementation of various
 	  IPv6 multicast APIs which need to be resolved in the API surface
 	  before the implementation is fully compatible with KAME userland
 	  use, and these are mostly to do with interface index treatment.
 
 	* The literature available discusses the use of either the delta / ASM
 	  API with setsockopt(2)/getsockopt(2), or the full-state / ASM API
 	  using setsourcefilter(3)/getsourcefilter(3). For more information
 	  please refer to RFC 3768, 'Socket Interface Extensions for
 	  Multicast Source Filters'.
 
 	* Applications which use the published RFC 3678 APIs should be fine.
 
 	For systems administrators:
 
 	* The mtest(8) utility has been refactored to support IPv6, in
 	  addition to IPv4. Interface addresses are no longer accepted
 	  as arguments, their names must be used instead. The utility
 	  will map the interface name to its first IPv4 address as
 	  returned by getifaddrs(3).
 
 	* The ifmcstat(8) utility has also been updated to print the MLDv2
 	  endpoint state and source filter lists via sysctl(3).
 
 	* The net.inet6.ip6.mcast.loop sysctl may be tuned to 0 to disable
 	  loopback of IPv6 multicast datagrams by default; it defaults to 1
 	  to preserve the existing behaviour. Disabling multicast loopback is
 	  recommended for optimal system performance.
 
 	* The IPv6 MROUTING code has been changed to examine this sysctl
 	  instead of attempting to perform a group lookup before looping
 	  back forwarded datagrams.
 
 	Bump __FreeBSD_version to 800084.
 
 20090422:
 	Implement low-level Bluetooth HCI API.
 	Bump __FreeBSD_version to 800083.
 
 20090419:
 	The layout of struct malloc_type, used by modules to register new
 	memory allocation types, has changed.  Most modules will need to
 	be rebuilt or panics may be experienced.
 	Bump __FreeBSD_version to 800081.
 
 20090415:
 	Anticipate overflowing inp_flags - add inp_flags2.
 	This changes most offsets in inpcb, so checking v4 connection
 	state will require a world rebuild.
 	Bump __FreeBSD_version to 800080.
 
 20090415:
 	Add an llentry to struct route and struct route_in6. Modules
 	embedding a struct route will need to be recompiled.
 	Bump __FreeBSD_version to 800079.
 
 20090414:
 	The size of rt_metrics_lite and by extension rtentry has changed.
 	Networking administration apps will need to be recompiled.
 	The route command now supports show as an alias for get, weighting
 	of routes, sticky and nostick flags to alter the behavior of stateful
 	load balancing.
 	Bump __FreeBSD_version to 800078.
 
 20090408:
 	Do not use Giant for kbdmux(4) locking. This is wrong and
 	apparently causing more problems than it solves. This will
 	re-open the issue where interrupt handlers may race with
 	kbdmux(4) in polling mode. Typical symptoms include (but
 	not limited to) duplicated and/or missing characters when
 	low level console functions (such as gets) are used while
 	interrupts are enabled (for example geli password prompt,
 	mountroot prompt etc.). Disabling kbdmux(4) may help.
 
 20090407:
 	The size of structs vnet_net, vnet_inet and vnet_ipfw has changed;
 	kernel modules referencing any of the above need to be recompiled.
 	Bump __FreeBSD_version to 800075.
 
 20090320:
 	GEOM_PART has become the default partition slicer for storage devices,
 	replacing GEOM_MBR, GEOM_BSD, GEOM_PC98 and GEOM_GPT slicers. It
 	introduces some changes:
 
 	MSDOS/EBR: the devices created from MSDOS extended partition entries
 	(EBR) can be named differently than with GEOM_MBR and are now symlinks
 	to devices with offset-based names. fstabs may need to be modified.
 
 	BSD: the "geometry does not match label" warning is harmless in most
 	cases but it points to problems in file system misalignment with
 	disk geometry. The "c" partition is now implicit, covers the whole
 	top-level drive and cannot be (mis)used by users.
 
 	General: Kernel dumps are now not allowed to be written to devices
 	whose partition types indicate they are meant to be used for file
 	systems (or, in case of MSDOS partitions, as something else than
 	the "386BSD" type).
 
 	Most of these changes date approximately from 200812.
 
 20090319:
 	The uscanner(4) driver has been removed from the kernel. This follows
 	Linux removing theirs in 2.6 and making libusb the default interface
 	(supported by sane).
 
 20090319:
 	The multicast forwarding code has been cleaned up. netstat(1)
 	only relies on KVM now for printing bandwidth upcall meters.
 	The IPv4 and IPv6 modules are split into ip_mroute_mod and
 	ip6_mroute_mod respectively. The config(5) options for statically
 	compiling this code remain the same, i.e. 'options MROUTING'.
 
 20090315:
 	Support for the IFF_NEEDSGIANT network interface flag has been
 	removed, which means that non-MPSAFE network device drivers are no
 	longer supported.  In particular, if_ar, if_sr, and network device
 	drivers from the old (legacy) USB stack can no longer be built or
 	used.
 
 20090313:
 	POSIX.1 Native Language Support (NLS) has been enabled in libc and
 	a bunch of new language catalog files have also been added.
 	This means that some common libc messages are now localized and
 	they depend on the LC_MESSAGES environmental variable.
 
 20090313:
 	The k8temp(4) driver has been renamed to amdtemp(4) since
 	support for Family 10 and Family 11 CPU families was added.
 
 20090309:
 	IGMPv3 and Source-Specific Multicast (SSM) have been merged
 	to the IPv4 stack. VIMAGE hooks are in but not yet used.
 
 	For kernel developers, the most important changes are that the
 	ip_output() and ip_input() paths no longer take the IN_MULTI_LOCK(),
 	and this lock has been downgraded to a non-recursive mutex.
 
 	Transport protocols (UDP, Raw IP) are now responsible for filtering
 	inbound multicast traffic according to group membership and source
 	filters. The imo_multicast_filter() KPI exists for this purpose.
 	Transports which do not use multicast (SCTP, TCP) already reject
 	multicast by default. Forwarding and receive performance may improve
 	as a mutex acquisition is no longer needed in the ip_input()
 	low-level input path.  in_addmulti() and in_delmulti() are shimmed
 	to new KPIs which exist to support SSM in-kernel.
 
 	For application developers, it is recommended that loopback of
 	multicast datagrams be disabled for best performance, as this
 	will still cause the lock to be taken for each looped-back
 	datagram transmission. The net.inet.ip.mcast.loop sysctl may
 	be tuned to 0 to disable loopback by default; it defaults to 1
 	to preserve the existing behaviour.
 
 	For systems administrators, to obtain best performance with
 	multicast reception and multiple groups, it is always recommended
 	that a card with a suitably precise hash filter is used. Hash
 	collisions will still result in the lock being taken within the
 	transport protocol input path to check group membership.
 
 	If deploying FreeBSD in an environment with IGMP snooping switches,
 	it is recommended that the net.inet.igmp.sendlocal sysctl remain
 	enabled; this forces 224.0.0.0/24 group membership to be announced
 	via IGMP.
 
 	The size of 'struct igmpstat' has changed; netstat needs to be
 	recompiled to reflect this.
 	Bump __FreeBSD_version to 800070.
 
 20090309:
 	libusb20.so.1 is now installed as libusb.so.1 and the ports system
 	updated to use it. This requires a buildworld/installworld in order to
 	update the library and dependencies (usbconfig, etc). Its advisable to
 	rebuild all ports which uses libusb. More specific directions are given
 	in the ports collection UPDATING file. Any /etc/libmap.conf entries for
 	libusb are no longer required and can be removed.
 
 20090302:
 	A workaround is committed to allow the creation of System V shared
 	memory segment of size > 2 GB on the 64-bit architectures.
 	Due to a limitation of the existing ABI, the shm_segsz member
 	of the struct shmid_ds, returned by shmctl(IPC_STAT) call is
 	wrong for large segments. Note that limits must be explicitly
 	raised to allow such segments to be created.
 
 20090301:
 	The layout of struct ifnet has changed, requiring a rebuild of all
 	network device driver modules.
 
 20090227:
 	The /dev handling for the new USB stack has changed, a
 	buildworld/installworld is required for libusb20.
 
 20090223:
 	The new USB2 stack has now been permanently moved in and all kernel and
 	module names reverted to their previous values (eg, usb, ehci, ohci,
 	ums, ...).  The old usb stack can be compiled in by prefixing the name
 	with the letter 'o', the old usb modules have been removed.
 	Updating entry 20090216 for xorg and 20090215 for libmap may still
 	apply.
 
 20090217:
 	The rc.conf(5) option if_up_delay has been renamed to
 	defaultroute_delay to better reflect its purpose. If you have
 	customized this setting in /etc/rc.conf you need to update it to
 	use the new name.
 
 20090216:
 	xorg 7.4 wants to configure its input devices via hald which does not
 	yet work with USB2. If the keyboard/mouse does not work in xorg then
 	add
 		Option "AllowEmptyInput" "off"
 	to your ServerLayout section.  This will cause X to use the configured
 	kbd and mouse sections from your xorg.conf.
 
 20090215:
 	The GENERIC kernels for all architectures now default to the new USB2
 	stack. No kernel config options or code have been removed so if a
 	problem arises please report it and optionally revert to the old USB
 	stack. If you are loading USB kernel modules or have a custom kernel
 	that includes GENERIC then ensure that usb names are also changed over,
 	eg uftdi -> usb2_serial_ftdi.
 
 	Older programs linked against the ports libusb 0.1 need to be
 	redirected to the new stack's libusb20.  /etc/libmap.conf can
 	be used for this:
 		# Map old usb library to new one for usb2 stack
 		libusb-0.1.so.8	libusb20.so.1
 
 20090209:
 	All USB ethernet devices now attach as interfaces under the name ueN
 	(eg. ue0). This is to provide a predictable name as vendors often
 	change usb chipsets in a product without notice.
 
 20090203:
 	The ichsmb(4) driver has been changed to require SMBus slave
 	addresses be left-justified (xxxxxxx0b) rather than right-justified.
 	All of the other SMBus controller drivers require left-justified
 	slave addresses, so this change makes all the drivers provide the
 	same interface.
 
 20090201:
 	INET6 statistics (struct ip6stat) was updated.
 	netstat(1) needs to be recompiled.
 
 20090119:
 	NTFS has been removed from GENERIC kernel on amd64 to match
 	GENERIC on i386. Should not cause any issues since mount_ntfs(8)
 	will load ntfs.ko module automatically when NTFS support is
 	actually needed, unless ntfs.ko is not installed or security
 	level prohibits loading kernel modules. If either is the case,
 	"options NTFS" has to be added into kernel config.
 
 20090115:
 	TCP Appropriate Byte Counting (RFC 3465) support added to kernel.
 	New field in struct tcpcb breaks ABI, so bump __FreeBSD_version to
 	800061. User space tools that rely on the size of struct tcpcb in
 	tcp_var.h (e.g. sockstat) need to be recompiled.
 
 20081225:
 	ng_tty(4) module updated to match the new TTY subsystem.
 	Due to API change, user-level applications must be updated.
 	New API support added to mpd5 CVS and expected to be present
 	in next mpd5.3 release.
 
 20081219:
 	With __FreeBSD_version 800060 the makefs tool is part of
 	the base system (it was a port).
 
 20081216:
 	The afdata and ifnet locks have been changed from mutexes to
 	rwlocks, network modules will need to be re-compiled.
 
 20081214:
 	__FreeBSD_version 800059 incorporates the new arp-v2 rewrite.
 	RTF_CLONING, RTF_LLINFO and RTF_WASCLONED flags are eliminated.
 	The new code reduced struct rtentry{} by 16 bytes on 32-bit
 	architecture and 40 bytes on 64-bit architecture. The userland
 	applications "arp" and "ndp" have been updated accordingly.
 	The output from "netstat -r" shows only routing entries and
 	none of the L2 information.
 
 20081130:
 	__FreeBSD_version 800057 marks the switchover from the
 	binary ath hal to source code. Users must add the line:
 
 	options	AH_SUPPORT_AR5416
 
 	to their kernel config files when specifying:
 
 	device	ath_hal
 
 	The ath_hal module no longer exists; the code is now compiled
 	together with the driver in the ath module.  It is now
 	possible to tailor chip support (i.e. reduce the set of chips
 	and thereby the code size); consult ath_hal(4) for details.
 
 20081121:
 	__FreeBSD_version 800054 adds memory barriers to
 	, new interfaces to ifnet to facilitate
 	multiple hardware transmit queues for cards that support
 	them, and a lock-less ring-buffer implementation to
 	enable drivers to more efficiently manage queueing of
 	packets.
 
 20081117:
 	A new version of ZFS (version 13) has been merged to -HEAD.
 	This version has zpool attribute "listsnapshots" off by
 	default, which means "zfs list" does not show snapshots,
 	and is the same as Solaris behavior.
 
 20081028:
 	dummynet(4) ABI has changed. ipfw(8) needs to be recompiled.
 
 20081009:
 	The uhci, ohci, ehci and slhci USB Host controller drivers have
 	been put into separate modules. If you load the usb module
 	separately through loader.conf you will need to load the
 	appropriate *hci module as well. E.g. for a UHCI-based USB 2.0
 	controller add the following to loader.conf:
 
 		uhci_load="YES"
 		ehci_load="YES"
 
 20081009:
 	The ABI used by the PMC toolset has changed.  Please keep
 	userland (libpmc(3)) and the kernel module (hwpmc(4)) in
 	sync.
 
 20081009:
 	atapci kernel module now includes only generic PCI ATA
 	driver. AHCI driver moved to ataahci kernel module.
 	All vendor-specific code moved into separate kernel modules:
 	ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek,
 	atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron,
 	atamarvell, atamicron, atanational, atanetcell, atanvidia,
 	atapromise, ataserverworks, atasiliconimage, atasis, atavia
 
 20080820:
 	The TTY subsystem of the kernel has been replaced by a new
 	implementation, which provides better scalability and an
 	improved driver model. Most common drivers have been migrated to
 	the new TTY subsystem, while others have not. The following
 	drivers have not yet been ported to the new TTY layer:
 
 	PCI/ISA:
 		cy, digi, rc, rp, sio
 
 	USB:
 		ubser, ucycom
 
 	Line disciplines:
 		ng_h4, ng_tty, ppp, sl, snp
 
 	Adding these drivers to your kernel configuration file shall
 	cause compilation to fail.
 
 20080818:
 	ntpd has been upgraded to 4.2.4p5.
 
 20080801:
 	OpenSSH has been upgraded to 5.1p1.
 
 	For many years, FreeBSD's version of OpenSSH preferred DSA
 	over RSA for host and user authentication keys.  With this
 	upgrade, we've switched to the vendor's default of RSA over
 	DSA.  This may cause upgraded clients to warn about unknown
 	host keys even for previously known hosts.  Users should
 	follow the usual procedure for verifying host keys before
 	accepting the RSA key.
 
 	This can be circumvented by setting the "HostKeyAlgorithms"
 	option to "ssh-dss,ssh-rsa" in ~/.ssh/config or on the ssh
 	command line.
 
 	Please note that the sequence of keys offered for
 	authentication has been changed as well.  You may want to
 	specify IdentityFile in a different order to revert this
 	behavior.
 
 20080713:
 	The sio(4) driver has been removed from the i386 and amd64
 	kernel configuration files. This means uart(4) is now the
 	default serial port driver on those platforms as well.
 
 	To prevent collisions with the sio(4) driver, the uart(4) driver
 	uses different names for its device nodes. This means the
 	onboard serial port will now most likely be called "ttyu0"
 	instead of "ttyd0". You may need to reconfigure applications to
 	use the new device names.
 
 	When using the serial port as a boot console, be sure to update
 	/boot/device.hints and /etc/ttys before booting the new kernel.
 	If you forget to do so, you can still manually specify the hints
 	at the loader prompt:
 
 		set hint.uart.0.at="isa"
 		set hint.uart.0.port="0x3F8"
 		set hint.uart.0.flags="0x10"
 		set hint.uart.0.irq="4"
 		boot -s
 
 20080609:
 	The gpt(8) utility has been removed. Use gpart(8) to partition
 	disks instead.
 
 20080603:
 	The version that Linuxulator emulates was changed from 2.4.2
 	to 2.6.16. If you experience any problems with Linux binaries
 	please try to set sysctl compat.linux.osrelease to 2.4.2 and
 	if it fixes the problem contact emulation mailing list.
 
 20080525:
 	ISDN4BSD (I4B) was removed from the src tree. You may need to
 	update a your kernel configuration and remove relevant entries.
 
 20080509:
 	I have checked in code to support multiple routing tables.
 	See the man pages setfib(1) and setfib(2).
 	This is a hopefully backwards compatible version,
 	but to make use of it you need to compile your kernel
 	with options ROUTETABLES=2 (or more up to 16).
 
 20080420:
 	The 802.11 wireless support was redone to enable multi-bss
 	operation on devices that are capable.  The underlying device
 	is no longer used directly but instead wlanX devices are
 	cloned with ifconfig.  This requires changes to rc.conf files.
 	For example, change:
 		ifconfig_ath0="WPA DHCP"
 	to
 		wlans_ath0=wlan0
 		ifconfig_wlan0="WPA DHCP"
 	see rc.conf(5) for more details.  In addition, mergemaster of
 	/etc/rc.d is highly recommended.  Simultaneous update of userland
 	and kernel wouldn't hurt either.
 
 	As part of the multi-bss changes the wlan_scan_ap and wlan_scan_sta
 	modules were merged into the base wlan module.  All references
 	to these modules (e.g. in kernel config files) must be removed.
 
 20080408:
 	psm(4) has gained write(2) support in native operation level.
 	Arbitrary commands can be written to /dev/psm%d and status can
 	be read back from it.  Therefore, an application is responsible
 	for status validation and error recovery.  It is a no-op in
 	other operation levels.
 
 20080312:
 	Support for KSE threading has been removed from the kernel.  To
 	run legacy applications linked against KSE libmap.conf may
 	be used.  The following libmap.conf may be used to ensure
 	compatibility with any prior release:
 
 	libpthread.so.1 libthr.so.1
 	libpthread.so.2 libthr.so.2
 	libkse.so.3 libthr.so.3
 
 20080301:
 	The layout of struct vmspace has changed. This affects libkvm
 	and any executables that link against libkvm and use the
 	kvm_getprocs() function. In particular, but not exclusively,
 	it affects ps(1), fstat(1), pkill(1), systat(1), top(1) and w(1).
 	The effects are minimal, but it's advisable to upgrade world
 	nonetheless.
 
 20080229:
 	The latest em driver no longer has support in it for the
 	82575 adapter, this is now moved to the igb driver. The
 	split was done to make new features that are incompatible
 	with older hardware easier to do.
 
 20080220:
 	The new geom_lvm(4) geom class has been renamed to geom_linux_lvm(4),
 	likewise the kernel option is now GEOM_LINUX_LVM.
 
 20080211:
 	The default NFS mount mode has changed from UDP to TCP for
 	increased reliability.  If you rely on (insecurely) NFS
 	mounting across a firewall you may need to update your
 	firewall rules.
 
 20080208:
 	Belatedly note the addition of m_collapse for compacting
 	mbuf chains.
 
 20080126:
 	The fts(3) structures have been changed to use adequate
 	integer types for their members and so to be able to cope
 	with huge file trees.  The old fts(3) ABI is preserved
 	through symbol versioning in libc, so third-party binaries
 	using fts(3) should still work, although they will not take
 	advantage of the extended types.  At the same time, some
 	third-party software might fail to build after this change
 	due to unportable assumptions made in its source code about
 	fts(3) structure members.  Such software should be fixed
 	by its vendor or, in the worst case, in the ports tree.
 	FreeBSD_version 800015 marks this change for the unlikely
 	case that a portable fix is impossible.
 
 20080123:
 	To upgrade to -current after this date, you must be running
 	FreeBSD not older than 6.0-RELEASE.  Upgrading to -current
 	from 5.x now requires a stop over at RELENG_6 or RELENG_7 systems.
 
 20071128:
 	The ADAPTIVE_GIANT kernel option has been retired because its
 	functionality is the default now.
 
 20071118:
 	The AT keyboard emulation of sunkbd(4) has been turned on
 	by default. In order to make the special symbols of the Sun
 	keyboards driven by sunkbd(4) work under X these now have
 	to be configured the same way as Sun USB keyboards driven
 	by ukbd(4) (which also does AT keyboard emulation), f.e.:
 
 	Option	"XkbLayout" "us"
 	Option	"XkbRules" "xorg"
 	Option	"XkbSymbols" "pc(pc105)+sun_vndr/usb(sun_usb)+us"
 
 20071024:
 	It has been decided that it is desirable to provide ABI
 	backwards compatibility to the FreeBSD 4/5/6 versions of the
 	PCIOCGETCONF, PCIOCREAD and PCIOCWRITE IOCTLs, which was
 	broken with the introduction of PCI domain support (see the
 	20070930 entry). Unfortunately, this required the ABI of
 	PCIOCGETCONF to be broken again in order to be able to
 	provide backwards compatibility to the old version of that
 	IOCTL. Thus consumers of PCIOCGETCONF have to be recompiled
 	again. As for prominent ports this affects neither pciutils
 	nor xorg-server this time, the hal port needs to be rebuilt
 	however.
 
 20071020:
 	The misnamed kthread_create() and friends have been renamed
 	to kproc_create() etc. Many of the callers already
 	used kproc_start()..
 	I will return kthread_create() and friends in a while
 	with implementations that actually create threads, not procs.
 	Renaming corresponds with version 800002.
 
 20071010:
 	RELENG_7 branched.
 
 COMMON ITEMS:
 
 	General Notes
 	-------------
 	Avoid using make -j when upgrading.  While generally safe, there are
 	sometimes problems using -j to upgrade.  If your upgrade fails with
 	-j, please try again without -j.  From time to time in the past there
 	have been problems using -j with buildworld and/or installworld.  This
 	is especially true when upgrading between "distant" versions (eg one
 	that cross a major release boundary or several minor releases, or when
 	several months have passed on the -current branch).
 
 	Sometimes, obscure build problems are the result of environment
 	poisoning.  This can happen because the make utility reads its
 	environment when searching for values for global variables.  To run
 	your build attempts in an "environmental clean room", prefix all make
 	commands with 'env -i '.  See the env(1) manual page for more details.
 
 	When upgrading from one major version to another it is generally best
 	to upgrade to the latest code in the currently installed branch first,
 	then do an upgrade to the new branch. This is the best-tested upgrade
 	path, and has the highest probability of being successful.  Please try
 	this approach before reporting problems with a major version upgrade.
 
 	ZFS notes
 	---------
 	When upgrading the boot ZFS pool to a new version, always follow
 	these two steps:
 
 	1.) recompile and reinstall the ZFS boot loader and boot block
 	(this is part of "make buildworld" and "make installworld")
 
 	2.) update the ZFS boot block on your boot drive
 
 	The following example updates the ZFS boot block on the first
 	partition (freebsd-boot) of a GPT partitioned drive ad0:
 	"gpart bootcode -p /boot/gptzfsboot -i 1 ad0"
 
 	Non-boot pools do not need these updates.
 
 	To build a kernel
 	-----------------
 	If you are updating from a prior version of FreeBSD (even one just
 	a few days old), you should follow this procedure.  It is the most
 	failsafe as it uses a /usr/obj tree with a fresh mini-buildworld,
 
 	make kernel-toolchain
 	make -DALWAYS_CHECK_MAKE buildkernel KERNCONF=YOUR_KERNEL_HERE
 	make -DALWAYS_CHECK_MAKE installkernel KERNCONF=YOUR_KERNEL_HERE
 
 	To test a kernel once
 	---------------------
 	If you just want to boot a kernel once (because you are not sure
 	if it works, or if you want to boot a known bad kernel to provide
 	debugging information) run
 	make installkernel KERNCONF=YOUR_KERNEL_HERE KODIR=/boot/testkernel
 	nextboot -k testkernel
 
 	To just build a kernel when you know that it won't mess you up
 	--------------------------------------------------------------
 	This assumes you are already running a CURRENT system.  Replace
 	${arch} with the architecture of your machine (e.g. "i386",
 	"arm", "amd64", "ia64", "pc98", "sparc64", "powerpc", "mips", etc).
 
 	cd src/sys/${arch}/conf
 	config KERNEL_NAME_HERE
 	cd ../compile/KERNEL_NAME_HERE
 	make depend
 	make
 	make install
 
 	If this fails, go to the "To build a kernel" section.
 
 	To rebuild everything and install it on the current system.
 	-----------------------------------------------------------
 	# Note: sometimes if you are running current you gotta do more than
 	# is listed here if you are upgrading from a really old current.
 
 	
 	make buildworld
 	make kernel KERNCONF=YOUR_KERNEL_HERE
 							[1]
 					[3]
 	mergemaster -p					[5]
 	make installworld
 	mergemaster -i					[4]
 	make delete-old					[6]
 	
 
 
 	To cross-install current onto a separate partition
 	--------------------------------------------------
 	# In this approach we use a separate partition to hold
 	# current's root, 'usr', and 'var' directories.   A partition
 	# holding "/", "/usr" and "/var" should be about 2GB in
 	# size.
 
 	
 	
 	make buildworld
 	make buildkernel KERNCONF=YOUR_KERNEL_HERE
 	
 	
 	make installworld DESTDIR=${CURRENT_ROOT}
 	make distribution DESTDIR=${CURRENT_ROOT} # if newfs'd
 	make installkernel KERNCONF=YOUR_KERNEL_HERE DESTDIR=${CURRENT_ROOT}
 	cp /etc/fstab ${CURRENT_ROOT}/etc/fstab 		   # if newfs'd
 	
 	
 	
 	
 	
 
 
 	To upgrade in-place from stable to current
 	----------------------------------------------
 	
 	make buildworld					[9]
 	make kernel KERNCONF=YOUR_KERNEL_HERE		[8]
 							[1]
 					[3]
 	mergemaster -p					[5]
 	make installworld
 	mergemaster -i					[4]
 	make delete-old					[6]
 	
 
 	Make sure that you've read the UPDATING file to understand the
 	tweaks to various things you need.  At this point in the life
 	cycle of current, things change often and you are on your own
 	to cope.  The defaults can also change, so please read ALL of
 	the UPDATING entries.
 
 	Also, if you are tracking -current, you must be subscribed to
 	freebsd-current@freebsd.org.  Make sure that before you update
 	your sources that you have read and understood all the recent
 	messages there.  If in doubt, please track -stable which has
 	much fewer pitfalls.
 
 	[1] If you have third party modules, such as vmware, you
 	should disable them at this point so they don't crash your
 	system on reboot.
 
 	[3] From the bootblocks, boot -s, and then do
 		fsck -p
 		mount -u /
 		mount -a
 		cd src
 		adjkerntz -i		# if CMOS is wall time
 	Also, when doing a major release upgrade, it is required that
 	you boot into single user mode to do the installworld.
 
 	[4] Note: This step is non-optional.  Failure to do this step
 	can result in a significant reduction in the functionality of the
 	system.  Attempting to do it by hand is not recommended and those
 	that pursue this avenue should read this file carefully, as well
 	as the archives of freebsd-current and freebsd-hackers mailing lists
 	for potential gotchas.  The -U option is also useful to consider.
 	See mergemaster(8) for more information.
 
 	[5] Usually this step is a noop.  However, from time to time
 	you may need to do this if you get unknown user in the following
 	step.  It never hurts to do it all the time.  You may need to
 	install a new mergemaster (cd src/usr.sbin/mergemaster && make
 	install) after the buildworld before this step if you last updated
 	from [78]-stable or 9-stable before 20130430.
 
 	[6] This only deletes old files and directories. Old libraries
 	can be deleted by "make delete-old-libs", but you have to make
 	sure that no program is using those libraries anymore.
 
 	[8] In order to have a kernel that can run the 4.x binaries needed to
 	do an installworld, you must include the COMPAT_FREEBSD4 option in
 	your kernel.  Failure to do so may leave you with a system that is
 	hard to boot to recover. A similar kernel option COMPAT_FREEBSD5 is
 	required to run the 5.x binaries on more recent kernels.  And so on
 	for COMPAT_FREEBSD6 and COMPAT_FREEBSD7.
 
 	Make sure that you merge any new devices from GENERIC since the
 	last time you updated your kernel config file.
 
 	[9] When checking out sources, you must include the -P flag to have
 	cvs prune empty directories.
 
 	If CPUTYPE is defined in your /etc/make.conf, make sure to use the
 	"?=" instead of the "=" assignment operator, so that buildworld can
 	override the CPUTYPE if it needs to.
 
 	MAKEOBJDIRPREFIX must be defined in an environment variable, and
 	not on the command line, or in /etc/make.conf.  buildworld will
 	warn if it is improperly defined.
 FORMAT:
 
 This file contains a list, in reverse chronological order, of major
 breakages in tracking -current.  It is not guaranteed to be a complete
 list of such breakages, and only contains entries since October 10, 2007.
 If you need to see UPDATING entries from before that date, you will need
 to fetch an UPDATING file from an older FreeBSD release.
 
 Copyright information:
 
 Copyright 1998-2009 M. Warner Losh.  All Rights Reserved.
 
 Redistribution, publication, translation and use, with or without
 modification, in full or in part, in any form or format of this
 document are permitted without further permission from the author.
 
 THIS DOCUMENT IS PROVIDED BY WARNER LOSH ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL WARNER LOSH BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 Contact Warner Losh if you have any questions about your use of
 this document.
 
 $FreeBSD$
Index: releng/9.3/crypto/openssl/crypto/bn/bn_print.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/bn/bn_print.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/bn/bn_print.c	(revision 284295)
@@ -1,338 +1,344 @@
 /* crypto/bn/bn_print.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include "bn_lcl.h"
 
 static const char Hex[]="0123456789ABCDEF";
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2hex(const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	char *buf;
 	char *p;
 
+	if (a->neg && BN_is_zero(a)) {
+	    /* "-0" == 3 bytes including NULL terminator */
+	    buf = OPENSSL_malloc(3);
+	} else {
+	    buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
+	}
 	buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2);
 	if (buf == NULL)
 		{
 		BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	p=buf;
 	if (a->neg) *(p++)='-';
 	if (BN_is_zero(a)) *(p++)='0';
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-8; j >= 0; j-=8)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0xff;
 			if (z || (v != 0))
 				{
 				*(p++)=Hex[v>>4];
 				*(p++)=Hex[v&0x0f];
 				z=1;
 				}
 			}
 		}
 	*p='\0';
 err:
 	return(buf);
 	}
 
 /* Must 'OPENSSL_free' the returned data */
 char *BN_bn2dec(const BIGNUM *a)
 	{
 	int i=0,num, ok = 0;
 	char *buf=NULL;
 	char *p;
 	BIGNUM *t=NULL;
 	BN_ULONG *bn_data=NULL,*lp;
 
 	/* get an upper bound for the length of the decimal integer
 	 * num <= (BN_num_bits(a) + 1) * log(2)
 	 *     <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1     (rounding error)
 	 *     <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 
 	 */
 	i=BN_num_bits(a)*3;
 	num=(i/10+i/1000+1)+1;
 	bn_data=(BN_ULONG *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
 	buf=(char *)OPENSSL_malloc(num+3);
 	if ((buf == NULL) || (bn_data == NULL))
 		{
 		BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	if ((t=BN_dup(a)) == NULL) goto err;
 
 #define BUF_REMAIN (num+3 - (size_t)(p - buf))
 	p=buf;
 	lp=bn_data;
 	if (BN_is_zero(t))
 		{
 		*(p++)='0';
 		*(p++)='\0';
 		}
 	else
 		{
 		if (BN_is_negative(t))
 			*p++ = '-';
 
 		i=0;
 		while (!BN_is_zero(t))
 			{
 			*lp=BN_div_word(t,BN_DEC_CONV);
 			lp++;
 			}
 		lp--;
 		/* We now have a series of blocks, BN_DEC_NUM chars
 		 * in length, where the last one needs truncation.
 		 * The blocks need to be reversed in order. */
 		BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT1,*lp);
 		while (*p) p++;
 		while (lp != bn_data)
 			{
 			lp--;
 			BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT2,*lp);
 			while (*p) p++;
 			}
 		}
 	ok = 1;
 err:
 	if (bn_data != NULL) OPENSSL_free(bn_data);
 	if (t != NULL) BN_free(t);
 	if (!ok && buf)
 		{
 		OPENSSL_free(buf);
 		buf = NULL;
 		}
 
 	return(buf);
 	}
 
 int BN_hex2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,h,m,i,j,k,c;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isxdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the hex digits, and it is 'i' long */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of hex digests; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=i; /* least significant 'hex' */
 	m=0;
 	h=0;
 	while (j > 0)
 		{
 		m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
 		l=0;
 		for (;;)
 			{
 			c=a[j-m];
 			if ((c >= '0') && (c <= '9')) k=c-'0';
 			else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
 			else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
 			else k=0; /* paranoia */
 			l=(l<<4)|k;
 
 			if (--m <= 0)
 				{
 				ret->d[h++]=l;
 				break;
 				}
 			}
 		j-=(BN_BYTES*2);
 		}
 	ret->top=h;
 	bn_correct_top(ret);
 	ret->neg=neg;
 
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 int BN_dec2bn(BIGNUM **bn, const char *a)
 	{
 	BIGNUM *ret=NULL;
 	BN_ULONG l=0;
 	int neg=0,i,j;
 	int num;
 
 	if ((a == NULL) || (*a == '\0')) return(0);
 	if (*a == '-') { neg=1; a++; }
 
 	for (i=0; isdigit((unsigned char) a[i]); i++)
 		;
 
 	num=i+neg;
 	if (bn == NULL) return(num);
 
 	/* a is the start of the digits, and it is 'i' long.
 	 * We chop it into BN_DEC_NUM digits at a time */
 	if (*bn == NULL)
 		{
 		if ((ret=BN_new()) == NULL) return(0);
 		}
 	else
 		{
 		ret= *bn;
 		BN_zero(ret);
 		}
 
 	/* i is the number of digests, a bit of an over expand; */
 	if (bn_expand(ret,i*4) == NULL) goto err;
 
 	j=BN_DEC_NUM-(i%BN_DEC_NUM);
 	if (j == BN_DEC_NUM) j=0;
 	l=0;
 	while (*a)
 		{
 		l*=10;
 		l+= *a-'0';
 		a++;
 		if (++j == BN_DEC_NUM)
 			{
 			BN_mul_word(ret,BN_DEC_CONV);
 			BN_add_word(ret,l);
 			l=0;
 			j=0;
 			}
 		}
 	ret->neg=neg;
 
 	bn_correct_top(ret);
 	*bn=ret;
 	bn_check_top(ret);
 	return(num);
 err:
 	if (*bn == NULL) BN_free(ret);
 	return(0);
 	}
 
 #ifndef OPENSSL_NO_BIO
 #ifndef OPENSSL_NO_FP_API
 int BN_print_fp(FILE *fp, const BIGNUM *a)
 	{
 	BIO *b;
 	int ret;
 
 	if ((b=BIO_new(BIO_s_file())) == NULL)
 		return(0);
 	BIO_set_fp(b,fp,BIO_NOCLOSE);
 	ret=BN_print(b,a);
 	BIO_free(b);
 	return(ret);
 	}
 #endif
 
 int BN_print(BIO *bp, const BIGNUM *a)
 	{
 	int i,j,v,z=0;
 	int ret=0;
 
 	if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
 	if (BN_is_zero(a) && (BIO_write(bp,"0",1) != 1)) goto end;
 	for (i=a->top-1; i >=0; i--)
 		{
 		for (j=BN_BITS2-4; j >= 0; j-=4)
 			{
 			/* strip leading zeros */
 			v=((int)(a->d[i]>>(long)j))&0x0f;
 			if (z || (v != 0))
 				{
 				if (BIO_write(bp,&(Hex[v]),1) != 1)
 					goto end;
 				z=1;
 				}
 			}
 		}
 	ret=1;
 end:
 	return(ret);
 	}
 #endif
Index: releng/9.3/crypto/openssl/crypto/cms/cms_smime.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/cms/cms_smime.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/cms/cms_smime.c	(revision 284295)
@@ -1,841 +1,841 @@
 /* crypto/cms/cms_smime.c */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  */
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include "cms_lcl.h"
 
 static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
 	{
 	unsigned char buf[4096];
 	int r = 0, i;
 	BIO *tmpout = NULL;
 
 	if (out == NULL)
 		tmpout = BIO_new(BIO_s_null());
 	else if (flags & CMS_TEXT)
 		{
 		tmpout = BIO_new(BIO_s_mem());
 		BIO_set_mem_eof_return(tmpout, 0);
 		}
 	else
 		tmpout = out;
 
 	if(!tmpout)
 		{
 		CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* Read all content through chain to process digest, decrypt etc */
 	for (;;)
 	{
 		i=BIO_read(in,buf,sizeof(buf));
 		if (i <= 0)
 			{
 			if (BIO_method_type(in) == BIO_TYPE_CIPHER)
 				{
 				if (!BIO_get_cipher_status(in))
 					goto err;
 				}
 			if (i < 0)
 				goto err;
 			break;
 			}
 				
 		if (tmpout && (BIO_write(tmpout, buf, i) != i))
 			goto err;
 	}
 
 	if(flags & CMS_TEXT)
 		{
 		if(!SMIME_text(tmpout, out))
 			{
 			CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
 			goto err;
 			}
 		}
 
 	r = 1;
 
 	err:
 	if (tmpout && (tmpout != out))
 		BIO_free(tmpout);
 	return r;
 
 	}
 
 static int check_content(CMS_ContentInfo *cms)
 	{
 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
 	if (!pos || !*pos)
 		{
 		CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
 		return 0;
 		}
 	return 1;
 	}
 
 static void do_free_upto(BIO *f, BIO *upto)
 	{
 	if (upto)
 		{
 		BIO *tbio;
 		do 
 			{
 			tbio = BIO_pop(f);
 			BIO_free(f);
 			f = tbio;
 			}
-		while (f != upto);
+		while (f && f != upto);
 		}
 	else
 		BIO_free_all(f);
 	}
 
 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data)
 		{
 		CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
 		return 0;
 		}
 	cont = CMS_dataInit(cms, NULL);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	BIO_free_all(cont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	cms = cms_Data_create();
 	if (!cms)
 		return NULL;
 
 	if (CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 
 	return NULL;
 	}
 
 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest)
 		{
 		CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	if (r)
 		r = cms_DigestedData_do_final(cms, cont, 1);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!md)
 		md = EVP_sha1();
 	cms = cms_DigestedData_create(md);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
 				const unsigned char *key, size_t keylen,
 				BIO *dcont, BIO *out, unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
 					CMS_R_TYPE_NOT_ENCRYPTED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
 					const unsigned char *key, size_t keylen,
 					unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (!cipher)
 		{
 		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
 		return NULL;
 		}
 	cms = CMS_ContentInfo_new();
 	if (!cms)
 		return NULL;
 	if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
 					X509_STORE *store,
 					STACK_OF(X509) *certs,
 					STACK_OF(X509_CRL) *crls,
 					unsigned int flags)
 	{
 	X509_STORE_CTX ctx;
 	X509 *signer;
 	int i, j, r = 0;
 	CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 	if (!X509_STORE_CTX_init(&ctx, store, signer, certs))
 		{
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_STORE_INIT_ERROR);
 		goto err;
 		}
 	X509_STORE_CTX_set_default(&ctx, "smime_sign");
 	if (crls)
 		X509_STORE_CTX_set0_crls(&ctx, crls);
 
 	i = X509_verify_cert(&ctx);
 	if (i <= 0)
 		{
 		j = X509_STORE_CTX_get_error(&ctx);
 		CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
 						CMS_R_CERTIFICATE_VERIFY_ERROR);
 		ERR_add_error_data(2, "Verify error:",
 					 X509_verify_cert_error_string(j));
 		goto err;
 		}
 	r = 1;
 	err:
 	X509_STORE_CTX_cleanup(&ctx);
 	return r;
 
 	}
 
 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
 		 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
 	{
 	CMS_SignerInfo *si;
 	STACK_OF(CMS_SignerInfo) *sinfos;
 	STACK_OF(X509) *cms_certs = NULL;
 	STACK_OF(X509_CRL) *crls = NULL;
 	X509 *signer;
 	int i, scount = 0, ret = 0;
 	BIO *cmsbio = NULL, *tmpin = NULL;
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	/* Attempt to find all signer certificates */
 
 	sinfos = CMS_get0_SignerInfos(cms);
 
 	if (sk_CMS_SignerInfo_num(sinfos) <= 0)
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
 		goto err;
 		}
 
 	for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 		{
 		si = sk_CMS_SignerInfo_value(sinfos, i);
 		CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
 		if (signer)
 			scount++;
 		}
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		scount += CMS_set1_signers_certs(cms, certs, flags);
 
 	if (scount != sk_CMS_SignerInfo_num(sinfos))
 		{
 		CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
 		goto err;
 		}
 
 	/* Attempt to verify all signers certs */
 
 	if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
 		{
 		cms_certs = CMS_get1_certs(cms);
 		if (!(flags & CMS_NOCRL))
 			crls = CMS_get1_crls(cms);
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (!cms_signerinfo_verify_cert(si, store,
 							cms_certs, crls, flags))
 				goto err;
 			}
 		}
 
 	/* Attempt to verify all SignerInfo signed attribute signatures */
 
 	if (!(flags & CMS_NO_ATTR_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_signed_get_attr_count(si) < 0)
 				continue;
 			if (CMS_SignerInfo_verify(si) <= 0)
 				goto err;
 			}
 		}
 
 	/* Performance optimization: if the content is a memory BIO then
 	 * store its contents in a temporary read only memory BIO. This
 	 * avoids potentially large numbers of slow copies of data which will
 	 * occur when reading from a read write memory BIO when signatures
 	 * are calculated.
 	 */
 
 	if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM))
 		{
 		char *ptr;
 		long len;
 		len = BIO_get_mem_data(dcont, &ptr);
 		tmpin = BIO_new_mem_buf(ptr, len);
 		if (tmpin == NULL)
 			{
 			CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		}
 	else
 		tmpin = dcont;
 		
 
 	cmsbio=CMS_dataInit(cms, tmpin);
 	if (!cmsbio)
 		goto err;
 
 	if (!cms_copy_content(out, cmsbio, flags))
 		goto err;
 
 	if (!(flags & CMS_NO_CONTENT_VERIFY))
 		{
 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
 			{
 			si = sk_CMS_SignerInfo_value(sinfos, i);
 			if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)
 				{
 				CMSerr(CMS_F_CMS_VERIFY,
 					CMS_R_CONTENT_VERIFY_ERROR);
 				goto err;
 				}
 			}
 		}
 
 	ret = 1;
 
 	err:
 	
 	if (dcont && (tmpin == dcont))
 		do_free_upto(cmsbio, dcont);
 	else
 		BIO_free_all(cmsbio);
 
 	if (cms_certs)
 		sk_X509_pop_free(cms_certs, X509_free);
 	if (crls)
 		sk_X509_CRL_pop_free(crls, X509_CRL_free);
 
 	return ret;
 	}
 
 int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
 			STACK_OF(X509) *certs,
 			X509_STORE *store, unsigned int flags)
 	{
 	int r;
 	r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
 	if (r <= 0)
 		return r;
 	return cms_Receipt_verify(rcms, ocms);
 	}
 
 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
 						BIO *data, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 
 	cms = CMS_ContentInfo_new();
 	if (!cms || !CMS_SignedData_init(cms))
 		goto merr;
 
 	if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
 		{
 		CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		X509 *x = sk_X509_value(certs, i);
 		if (!CMS_add1_cert(cms, x))
 			goto merr;
 		}
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
 
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 					X509 *signcert, EVP_PKEY *pkey,
 					STACK_OF(X509) *certs,
 					unsigned int flags)
 	{
 	CMS_SignerInfo *rct_si;
 	CMS_ContentInfo *cms = NULL;
 	ASN1_OCTET_STRING **pos, *os;
 	BIO *rct_cont = NULL;
 	int r = 0;
 
 	flags &= ~CMS_STREAM;
 	/* Not really detached but avoids content being allocated */
 	flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
 	if (!pkey || !signcert)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
 		return NULL;
 		}
 
 	/* Initialize signed data */
 
 	cms = CMS_sign(NULL, NULL, certs, NULL, flags);
 	if (!cms)
 		goto err;
 
 	/* Set inner content type to signed receipt */
 	if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
 		goto err;
 
 	rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
 	if (!rct_si)
 		{
 		CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
 		goto err;
 		}
 
 	os = cms_encode_Receipt(si);
 
 	if (!os)
 		goto err;
 
 	/* Set content to digest */
 	rct_cont = BIO_new_mem_buf(os->data, os->length);
 	if (!rct_cont)
 		goto err;
 
 	/* Add msgSigDigest attribute */
 
 	if (!cms_msgSigDigest_add1(rct_si, si))
 		goto err;
 
 	/* Finalize structure */
 	if (!CMS_final(cms, rct_cont, NULL, flags))
 		goto err;
 
 	/* Set embedded content */
 	pos = CMS_get0_content(cms);
 	*pos = os;
 
 	r = 1;
 
 	err:
 	if (rct_cont)
 		BIO_free(rct_cont);
 	if (r)
 		return cms;
 	CMS_ContentInfo_free(cms);
 	return NULL;
 
 	}
 
 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
 				const EVP_CIPHER *cipher, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	int i;
 	X509 *recip;
 	cms = CMS_EnvelopedData_create(cipher);
 	if (!cms)
 		goto merr;
 	for (i = 0; i < sk_X509_num(certs); i++)
 		{
 		recip = sk_X509_value(certs, i);
 		if (!CMS_add1_recipient_cert(cms, recip, flags))
 			{
 			CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
 			goto err;
 			}
 		}
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if ((flags & (CMS_STREAM|CMS_PARTIAL))
 		|| CMS_final(cms, data, NULL, flags))
 		return cms;
 	else
 		goto err;
 
 	merr:
 	CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
 	err:
 	if (cms)
 		CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	int debug = 0, ri_match = 0;
 	ris = CMS_get0_RecipientInfos(cms);
 	if (ris)
 		debug = cms->d.envelopedData->encryptedContentInfo->debug;
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
 				continue;
 		ri_match = 1;
 		/* If we have a cert try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
 			{
 			CMS_RecipientInfo_set0_pkey(ri, pk);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_pkey(ri, NULL);
 			if (cert)
 				{
 				/* If not debugging clear any error and
 				 * return success to avoid leaking of
 				 * information useful to MMA
 				 */
 				if (!debug)
 					{
 					ERR_clear_error();
 					return 1;
 					}
 				if (r > 0)
 					return 1;
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			/* If no cert and not debugging don't leave loop
 			 * after first successful decrypt. Always attempt
 			 * to decrypt all recipients to avoid leaking timing
 			 * of a successful decrypt.
 			 */
 			else if (r > 0 && debug)
 				return 1;
 			}
 		}
 	/* If no cert and not debugging always return success */
 	if (ri_match && !cert && !debug)
 		{
 		ERR_clear_error();
 		return 1;
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 
 int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
 				unsigned char *key, size_t keylen,
 				unsigned char *id, size_t idlen)
 	{
 	STACK_OF(CMS_RecipientInfo) *ris;
 	CMS_RecipientInfo *ri;
 	int i, r;
 	ris = CMS_get0_RecipientInfos(cms);
 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
 		{
 		ri = sk_CMS_RecipientInfo_value(ris, i);
 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
 				continue;
 
 		/* If we have an id try matching RecipientInfo
 		 * otherwise try them all.
 		 */
 		if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
 			{
 			CMS_RecipientInfo_set0_key(ri, key, keylen);
 			r = CMS_RecipientInfo_decrypt(cms, ri);
 			CMS_RecipientInfo_set0_key(ri, NULL, 0);
 			if (r > 0)
 				return 1;
 			if (id)
 				{
 				CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
 						CMS_R_DECRYPT_ERROR);
 				return 0;
 				}
 			ERR_clear_error();
 			}
 		}
 
 	CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
 	return 0;
 
 	}
 	
 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
 				BIO *dcont, BIO *out,
 				unsigned int flags)
 	{
 	int r;
 	BIO *cont;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
 		{
 		CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
 		return 0;
 		}
 	if (!dcont && !check_content(cms))
 		return 0;
 	if (flags & CMS_DEBUG_DECRYPT)
 		cms->d.envelopedData->encryptedContentInfo->debug = 1;
 	else
 		cms->d.envelopedData->encryptedContentInfo->debug = 0;
 	if (!pk && !cert && !dcont && !out)
 		return 1;
 	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
 		return 0;
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
 	{
 	BIO *cmsbio;
 	int ret = 0;
 	if (!(cmsbio = CMS_dataInit(cms, dcont)))
 		{
 		CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	SMIME_crlf_copy(data, cmsbio, flags);
 
 	(void)BIO_flush(cmsbio);
 
 
         if (!CMS_dataFinal(cms, cmsbio))
 		{
 		CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR);
 		goto err;
 		}
 
 	ret = 1;
 
 	err:
 	do_free_upto(cmsbio, dcont);
 
 	return ret;
 
 	}
 
 #ifdef ZLIB
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	BIO *cont;
 	int r;
 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData)
 		{
 		CMSerr(CMS_F_CMS_UNCOMPRESS,
 					CMS_R_TYPE_NOT_COMPRESSED_DATA);
 		return 0;
 		}
 
 	if (!dcont && !check_content(cms))
 		return 0;
 
 	cont = CMS_dataInit(cms, dcont);
 	if (!cont)
 		return 0;
 	r = cms_copy_content(out, cont, flags);
 	do_free_upto(cont, dcont);
 	return r;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMS_ContentInfo *cms;
 	if (comp_nid <= 0)
 		comp_nid = NID_zlib_compression;
 	cms = cms_CompressedData_create(comp_nid);
 	if (!cms)
 		return NULL;
 
 	if(!(flags & CMS_DETACHED))
 		{
 		flags &= ~CMS_STREAM;
 		CMS_set_detached(cms, 0);
 		}
 
 	if (CMS_final(cms, in, NULL, flags))
 		return cms;
 
 	CMS_ContentInfo_free(cms);
 	return NULL;
 	}
 
 #else
 
 int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 							unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return 0;
 	}
 
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 	{
 	CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 	return NULL;
 	}
 
 #endif
Index: releng/9.3/crypto/openssl/crypto/ec/ec2_smpl.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ec2_smpl.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ec2_smpl.c	(revision 284295)
@@ -1,976 +1,977 @@
 /* crypto/ec/ec2_smpl.c */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
  * to the OpenSSL project.
  *
  * The ECC Code is licensed pursuant to the OpenSSL open source
  * license provided below.
  *
  * The software is originally written by Sheueling Chang Shantz and
  * Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 
 #include "ec_lcl.h"
 
 
 const EC_METHOD *EC_GF2m_simple_method(void)
 	{
 	static const EC_METHOD ret = {
 		NID_X9_62_characteristic_two_field,
 		ec_GF2m_simple_group_init,
 		ec_GF2m_simple_group_finish,
 		ec_GF2m_simple_group_clear_finish,
 		ec_GF2m_simple_group_copy,
 		ec_GF2m_simple_group_set_curve,
 		ec_GF2m_simple_group_get_curve,
 		ec_GF2m_simple_group_get_degree,
 		ec_GF2m_simple_group_check_discriminant,
 		ec_GF2m_simple_point_init,
 		ec_GF2m_simple_point_finish,
 		ec_GF2m_simple_point_clear_finish,
 		ec_GF2m_simple_point_copy,
 		ec_GF2m_simple_point_set_to_infinity,
 		0 /* set_Jprojective_coordinates_GFp */,
 		0 /* get_Jprojective_coordinates_GFp */,
 		ec_GF2m_simple_point_set_affine_coordinates,
 		ec_GF2m_simple_point_get_affine_coordinates,
 		ec_GF2m_simple_set_compressed_coordinates,
 		ec_GF2m_simple_point2oct,
 		ec_GF2m_simple_oct2point,
 		ec_GF2m_simple_add,
 		ec_GF2m_simple_dbl,
 		ec_GF2m_simple_invert,
 		ec_GF2m_simple_is_at_infinity,
 		ec_GF2m_simple_is_on_curve,
 		ec_GF2m_simple_cmp,
 		ec_GF2m_simple_make_affine,
 		ec_GF2m_simple_points_make_affine,
 
 		/* the following three method functions are defined in ec2_mult.c */
 		ec_GF2m_simple_mul,
 		ec_GF2m_precompute_mult,
 		ec_GF2m_have_precompute_mult,
 
 		ec_GF2m_simple_field_mul,
 		ec_GF2m_simple_field_sqr,
 		ec_GF2m_simple_field_div,
 		0 /* field_encode */,
 		0 /* field_decode */,
 		0 /* field_set_to_one */ };
 
 	return &ret;
 	}
 
 
 /* Initialize a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_new.
  */
 int ec_GF2m_simple_group_init(EC_GROUP *group)
 	{
 	BN_init(&group->field);
 	BN_init(&group->a);
 	BN_init(&group->b);
 	return 1;
 	}
 
 
 /* Free a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_free.
  */
 void ec_GF2m_simple_group_finish(EC_GROUP *group)
 	{
 	BN_free(&group->field);
 	BN_free(&group->a);
 	BN_free(&group->b);
 	}
 
 
 /* Clear and free a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_clear_free.
  */
 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
 	{
 	BN_clear_free(&group->field);
 	BN_clear_free(&group->a);
 	BN_clear_free(&group->b);
 	group->poly[0] = 0;
 	group->poly[1] = 0;
 	group->poly[2] = 0;
 	group->poly[3] = 0;
 	group->poly[4] = 0;
 	}
 
 
 /* Copy a GF(2^m)-based EC_GROUP structure.
  * Note that all other members are handled by EC_GROUP_copy.
  */
 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	int i;
 	if (!BN_copy(&dest->field, &src->field)) return 0;
 	if (!BN_copy(&dest->a, &src->a)) return 0;
 	if (!BN_copy(&dest->b, &src->b)) return 0;
 	dest->poly[0] = src->poly[0];
 	dest->poly[1] = src->poly[1];
 	dest->poly[2] = src->poly[2];
 	dest->poly[3] = src->poly[3];
 	dest->poly[4] = src->poly[4];
 	if(bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
 		return 0;
 	if(bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
 		return 0;
 	for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
 	for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
 	return 1;
 	}
 
 
 /* Set the curve parameters of an EC_GROUP structure. */
 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0, i;
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
 	i = BN_GF2m_poly2arr(&group->field, group->poly, 5);
 	if ((i != 5) && (i != 3))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
 		goto err;
 		}
 
 	/* group->a */
 	if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
 	if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
 	for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
 	
 	/* group->b */
 	if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
 	if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
 	for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
 		
 	ret = 1;
   err:
 	return ret;
 	}
 
 
 /* Get the curve parameters of an EC_GROUP structure.
  * If p, a, or b are NULL then there values will not be set but the method will return with success.
  */
 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	
 	if (p != NULL)
 		{
 		if (!BN_copy(p, &group->field)) return 0;
 		}
 
 	if (a != NULL)
 		{
 		if (!BN_copy(a, &group->a)) goto err;
 		}
 
 	if (b != NULL)
 		{
 		if (!BN_copy(b, &group->b)) goto err;
 		}
 	
 	ret = 1;
 	
   err:
 	return ret;
 	}
 
 
 /* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
 	{
 	return BN_num_bits(&group->field)-1;
 	}
 
 
 /* Checks the discriminant of the curve.
  * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
  */
 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *b;
 	BN_CTX *new_ctx = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	b = BN_CTX_get(ctx);
 	if (b == NULL) goto err;
 
 	if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
 	
 	/* check the discriminant:
 	 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
 	 */
 	if (BN_is_zero(b)) goto err;
 
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Initializes an EC_POINT. */
 int ec_GF2m_simple_point_init(EC_POINT *point)
 	{
 	BN_init(&point->X);
 	BN_init(&point->Y);
 	BN_init(&point->Z);
 	return 1;
 	}
 
 
 /* Frees an EC_POINT. */
 void ec_GF2m_simple_point_finish(EC_POINT *point)
 	{
 	BN_free(&point->X);
 	BN_free(&point->Y);
 	BN_free(&point->Z);
 	}
 
 
 /* Clears and frees an EC_POINT. */
 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
 	{
 	BN_clear_free(&point->X);
 	BN_clear_free(&point->Y);
 	BN_clear_free(&point->Z);
 	point->Z_is_one = 0;
 	}
 
 
 /* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (!BN_copy(&dest->X, &src->X)) return 0;
 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
 	dest->Z_is_one = src->Z_is_one;
 
 	return 1;
 	}
 
 
 /* Set an EC_POINT to the point at infinity.  
  * A point at infinity is represented by having Z=0.
  */
 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	point->Z_is_one = 0;
 	BN_zero(&point->Z);
 	return 1;
 	}
 
 
 /* Set the coordinates of an EC_POINT using affine coordinates. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	int ret = 0;	
 	if (x == NULL || y == NULL)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if (!BN_copy(&point->X, x)) goto err;
 	BN_set_negative(&point->X, 0);
 	if (!BN_copy(&point->Y, y)) goto err;
 	BN_set_negative(&point->Y, 0);
 	if (!BN_copy(&point->Z, BN_value_one())) goto err;
 	BN_set_negative(&point->Z, 0);
 	point->Z_is_one = 1;
 	ret = 1;
 
   err:
 	return ret;
 	}
 
 
 /* Gets the affine coordinates of an EC_POINT. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	int ret = 0;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
 		return 0;
 		}
 
 	if (BN_cmp(&point->Z, BN_value_one())) 
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (x != NULL)
 		{
 		if (!BN_copy(x, &point->X)) goto err;
 		BN_set_negative(x, 0);
 		}
 	if (y != NULL)
 		{
 		if (!BN_copy(y, &point->Y)) goto err;
 		BN_set_negative(y, 0);
 		}
 	ret = 1;
 		
  err:
 	return ret;
 	}
 
 
 /* Include patented algorithms. */
 #include "ec2_smpt.c"
 
 
 /* Converts an EC_POINT to an octet string.  
  * If buf is NULL, the encoded length will be returned.
  * If the length len of buf is smaller than required an error will be returned.
  *
  * The point compression section of this function is patented by Certicom Corp. 
  * under US Patent 6,141,420.  Point compression is disabled by default and can 
  * be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at 
  * Configure-time.
  */
 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, i, skip;
 
 #ifndef OPENSSL_EC_BIN_PT_COMP
 	if ((form == POINT_CONVERSION_COMPRESSED) || (form == POINT_CONVERSION_HYBRID)) 
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED);
 		goto err;
 		}
 #endif
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		yxi = BN_CTX_get(ctx);
 		if (yxi == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 
 		buf[0] = form;
 #ifdef OPENSSL_EC_BIN_PT_COMP
 		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (BN_is_odd(yxi)) buf[0]++;
 			}
 #endif
 
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 /* Converts an octet string representation to an EC_POINT. 
  * Note that the simple implementation only uses affine coordinates.
  */
 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y, *yxi;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	yxi = BN_CTX_get(ctx);
 	if (yxi == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
 			if (y_bit != BN_is_odd(yxi))
 				{
 				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Computes a + b and stores the result in r.  r could be a or b, a could be b.
  * Uses algorithm A.10.2 of IEEE P1363.
  */
 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
 	int ret = 0;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		if (!EC_POINT_copy(r, b)) return 0;
 		return 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		{
 		if (!EC_POINT_copy(r, a)) return 0;
 		return 1;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x0 = BN_CTX_get(ctx);
 	y0 = BN_CTX_get(ctx);
 	x1 = BN_CTX_get(ctx);
 	y1 = BN_CTX_get(ctx);
 	x2 = BN_CTX_get(ctx);
 	y2 = BN_CTX_get(ctx);
 	s = BN_CTX_get(ctx);
 	t = BN_CTX_get(ctx);
 	if (t == NULL) goto err;
 
 	if (a->Z_is_one) 
 		{
 		if (!BN_copy(x0, &a->X)) goto err;
 		if (!BN_copy(y0, &a->Y)) goto err;
 		}
 	else
 		{
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
 		}
 	if (b->Z_is_one) 
 		{
 		if (!BN_copy(x1, &b->X)) goto err;
 		if (!BN_copy(y1, &b->Y)) goto err;
 		}
 	else
 		{
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
 		}
 
 
 	if (BN_GF2m_cmp(x0, x1))
 		{
 		if (!BN_GF2m_add(t, x0, x1)) goto err;
 		if (!BN_GF2m_add(s, y0, y1)) goto err;
 		if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
 		if (!BN_GF2m_add(x2, x2, s)) goto err;
 		if (!BN_GF2m_add(x2, x2, t)) goto err;
 		}
 	else
 		{
 		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
 			{
 			if (!EC_POINT_set_to_infinity(group, r)) goto err;
 			ret = 1;
 			goto err;
 			}
 		if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
 		if (!BN_GF2m_add(s, s, x1)) goto err;
 		
 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
 		if (!BN_GF2m_add(x2, x2, s)) goto err;
 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
 		}
 
 	if (!BN_GF2m_add(y2, x1, x2)) goto err;
 	if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
 	if (!BN_GF2m_add(y2, y2, x2)) goto err;
 	if (!BN_GF2m_add(y2, y2, y1)) goto err;
 
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Computes 2 * a and stores the result in r.  r could be a.
  * Uses algorithm A.10.2 of IEEE P1363.
  */
 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	return ec_GF2m_simple_add(group, r, a, a, ctx);
 	}
 
 
 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
 		/* point is its own inverse */
 		return 1;
 	
 	if (!EC_POINT_make_affine(group, point, ctx)) return 0;
 	return BN_GF2m_add(&point->Y, &point->X, &point->Y);
 	}
 
 
 /* Indicates whether the given point is the point at infinity. */
 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	return BN_is_zero(&point->Z);
 	}
 
 
 /* Determines whether the given EC_POINT is an actual point on the curve defined
  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
  *      y^2 + x*y = x^3 + a*x^2 + b.
  */
 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
 	{
 	int ret = -1;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *lh, *y2;
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 
 	if (EC_POINT_is_at_infinity(group, point))
 		return 1;
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;	
 
 	/* only support affine coordinates */
 	if (!point->Z_is_one) return -1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	y2 = BN_CTX_get(ctx);
 	lh = BN_CTX_get(ctx);
 	if (lh == NULL) goto err;
 
 	/* We have a curve defined by a Weierstrass equation
 	 *      y^2 + x*y = x^3 + a*x^2 + b.
 	 *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
 	 *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
 	 */
 	if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
 	if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
 	if (!BN_GF2m_add(lh, lh, y2)) goto err;
 	ret = BN_is_zero(lh);
  err:
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Indicates whether two points are equal.
  * Return values:
  *  -1   error
  *   0   equal (in affine coordinates)
  *   1   not equal
  */
 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	BIGNUM *aX, *aY, *bX, *bY;
 	BN_CTX *new_ctx = NULL;
 	int ret = -1;
 
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		return 1;
 	
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	aX = BN_CTX_get(ctx);
 	aY = BN_CTX_get(ctx);
 	bX = BN_CTX_get(ctx);
 	bY = BN_CTX_get(ctx);
 	if (bY == NULL) goto err;
 
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
 	ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
 
   err:	
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Forces the given EC_POINT to internally use affine coordinates. */
 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	int ret = 0;
 
 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
 		return 1;
 	
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 	
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 	if (!BN_copy(&point->X, x)) goto err;
 	if (!BN_copy(&point->Y, y)) goto err;
 	if (!BN_one(&point->Z)) goto err;
 	
 	ret = 1;		
 
   err:
 	if (ctx) BN_CTX_end(ctx);
 	if (new_ctx) BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	size_t i;
 
 	for (i = 0; i < num; i++)
 		{
 		if (!group->meth->make_affine(group, points[i], ctx)) return 0;
 		}
 
 	return 1;
 	}
 
 
 /* Wrapper to simple binary polynomial field multiplication implementation. */
 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
 	}
 
 
 /* Wrapper to simple binary polynomial field squaring implementation. */
 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
 	}
 
 
 /* Wrapper to simple binary polynomial field division implementation. */
 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
 	}
Index: releng/9.3/crypto/openssl/crypto/ec/ec_check.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ec_check.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ec_check.c	(revision 284295)
@@ -1,123 +1,123 @@
 /* crypto/ec/ec_check.c */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include "ec_lcl.h"
 #include 
 
 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *order;
 	BN_CTX *new_ctx = NULL;
 	EC_POINT *point = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	if ((order = BN_CTX_get(ctx)) == NULL) goto err;
 
 	/* check the discriminant */
 	if (!EC_GROUP_check_discriminant(group, ctx))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
 		goto err;
 		}
 
 	/* check the generator */
 	if (group->generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
 		goto err;
 		}
-	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
+	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	/* check the order of the generator */
 	if ((point = EC_POINT_new(group)) == NULL) goto err;
 	if (!EC_GROUP_get_order(group, order, ctx)) goto err; 
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
 		goto err;
 		}
 	
 	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
 	if (!EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	if (point)
 		EC_POINT_free(point);
 	return ret;
 	}
Index: releng/9.3/crypto/openssl/crypto/ec/ec_key.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ec_key.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ec_key.c	(revision 284295)
@@ -1,471 +1,471 @@
 /* crypto/ec/ec_key.c */
 /*
  * Written by Nils Larsch for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions originally developed by SUN MICROSYSTEMS, INC., and 
  * contributed to the OpenSSL project.
  */
 
 #include 
 #include "ec_lcl.h"
 #include 
 
 EC_KEY *EC_KEY_new(void)
 	{
 	EC_KEY *ret;
 
 	ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE);
 		return(NULL);
 		}
 
 	ret->version = 1;	
 	ret->group   = NULL;
 	ret->pub_key = NULL;
 	ret->priv_key= NULL;
 	ret->enc_flag= 0; 
 	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
 	ret->references= 1;
 	ret->method_data = NULL;
 	return(ret);
 	}
 
 EC_KEY *EC_KEY_new_by_curve_name(int nid)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	ret->group = EC_GROUP_new_by_curve_name(nid);
 	if (ret->group == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 void EC_KEY_free(EC_KEY *r)
 	{
 	int i;
 
 	if (r == NULL) return;
 
 	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"EC_KEY_free, bad reference count\n");
 		abort();
 		}
 #endif
 
 	if (r->group    != NULL) 
 		EC_GROUP_free(r->group);
 	if (r->pub_key  != NULL)
 		EC_POINT_free(r->pub_key);
 	if (r->priv_key != NULL)
 		BN_clear_free(r->priv_key);
 
 	EC_EX_DATA_free_all_data(&r->method_data);
 
 	OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
 
 	OPENSSL_free(r);
 	}
 
 EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest == NULL || src == NULL)
 		{
 		ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	/* copy the parameters */
 	if (src->group)
 		{
 		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
 		/* clear the old group */
 		if (dest->group)
 			EC_GROUP_free(dest->group);
 		dest->group = EC_GROUP_new(meth);
 		if (dest->group == NULL)
 			return NULL;
 		if (!EC_GROUP_copy(dest->group, src->group))
 			return NULL;
 		}
 	/*  copy the public key */
 	if (src->pub_key && src->group)
 		{
 		if (dest->pub_key)
 			EC_POINT_free(dest->pub_key);
 		dest->pub_key = EC_POINT_new(src->group);
 		if (dest->pub_key == NULL)
 			return NULL;
 		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
 			return NULL;
 		}
 	/* copy the private key */
 	if (src->priv_key)
 		{
 		if (dest->priv_key == NULL)
 			{
 			dest->priv_key = BN_new();
 			if (dest->priv_key == NULL)
 				return NULL;
 			}
 		if (!BN_copy(dest->priv_key, src->priv_key))
 			return NULL;
 		}
 	/* copy method/extra data */
 	EC_EX_DATA_free_all_data(&dest->method_data);
 
 	for (d = src->method_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	/* copy the rest */
 	dest->enc_flag  = src->enc_flag;
 	dest->conv_form = src->conv_form;
 	dest->version   = src->version;
 
 	return dest;
 	}
 
 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
 	{
 	EC_KEY *ret = EC_KEY_new();
 	if (ret == NULL)
 		return NULL;
 	if (EC_KEY_copy(ret, ec_key) == NULL)
 		{
 		EC_KEY_free(ret);
 		return NULL;
 		}
 	return ret;
 	}
 
 int EC_KEY_up_ref(EC_KEY *r)
 	{
 	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
 #ifdef REF_PRINT
 	REF_PRINT("EC_KEY",r);
 #endif
 #ifdef REF_CHECK
 	if (i < 2)
 		{
 		fprintf(stderr, "EC_KEY_up, bad reference count\n");
 		abort();
 		}
 #endif
 	return ((i > 1) ? 1 : 0);
 	}
 
 int EC_KEY_generate_key(EC_KEY *eckey)
 	{	
 	int	ok = 0;
 	BN_CTX	*ctx = NULL;
 	BIGNUM	*priv_key = NULL, *order = NULL;
 	EC_POINT *pub_key = NULL;
 
 	if (!eckey || !eckey->group)
 		{
 		ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if ((order = BN_new()) == NULL) goto err;
 	if ((ctx = BN_CTX_new()) == NULL) goto err;
 
 	if (eckey->priv_key == NULL)
 		{
 		priv_key = BN_new();
 		if (priv_key == NULL)
 			goto err;
 		}
 	else
 		priv_key = eckey->priv_key;
 
 	if (!EC_GROUP_get_order(eckey->group, order, ctx))
 		goto err;
 
 	do
 		if (!BN_rand_range(priv_key, order))
 			goto err;
 	while (BN_is_zero(priv_key));
 
 	if (eckey->pub_key == NULL)
 		{
 		pub_key = EC_POINT_new(eckey->group);
 		if (pub_key == NULL)
 			goto err;
 		}
 	else
 		pub_key = eckey->pub_key;
 
 	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
 		goto err;
 
 	eckey->priv_key = priv_key;
 	eckey->pub_key  = pub_key;
 
 	ok=1;
 
 err:	
 	if (order)
 		BN_free(order);
 	if (pub_key  != NULL && eckey->pub_key  == NULL)
 		EC_POINT_free(pub_key);
 	if (priv_key != NULL && eckey->priv_key == NULL)
 		BN_free(priv_key);
 	if (ctx != NULL)
 		BN_CTX_free(ctx);
 	return(ok);
 	}
 
 int EC_KEY_check_key(const EC_KEY *eckey)
 	{
 	int	ok   = 0;
 	BN_CTX	*ctx = NULL;
 	const BIGNUM	*order  = NULL;
 	EC_POINT *point = NULL;
 
 	if (!eckey || !eckey->group || !eckey->pub_key)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
 		goto err;
 		}
 
 	if ((ctx = BN_CTX_new()) == NULL)
 		goto err;
 	if ((point = EC_POINT_new(eckey->group)) == NULL)
 		goto err;
 
 	/* testing whether the pub_key is on the elliptic curve */
-	if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
+	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 	/* testing whether pub_key * order is the point at infinity */
 	order = &eckey->group->order;
 	if (BN_is_zero(order))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
 		goto err;
 		}
 	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 		goto err;
 		}
 	if (!EC_POINT_is_at_infinity(eckey->group, point))
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 		goto err;
 		}
 	/* in case the priv_key is present : 
 	 * check if generator * priv_key == pub_key 
 	 */
 	if (eckey->priv_key)
 		{
 		if (BN_cmp(eckey->priv_key, order) >= 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
 			goto err;
 			}
 		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
 			NULL, NULL, ctx))
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 
 			ctx) != 0)
 			{
 			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
 			goto err;
 			}
 		}
 	ok = 1;
 err:
 	if (ctx   != NULL)
 		BN_CTX_free(ctx);
 	if (point != NULL)
 		EC_POINT_free(point);
 	return(ok);
 	}
 
 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
 	{
 	return key->group;
 	}
 
 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
 	{
 	if (key->group != NULL)
 		EC_GROUP_free(key->group);
 	key->group = EC_GROUP_dup(group);
 	return (key->group == NULL) ? 0 : 1;
 	}
 
 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
 	{
 	return key->priv_key;
 	}
 
 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
 	{
 	if (key->priv_key)
 		BN_clear_free(key->priv_key);
 	key->priv_key = BN_dup(priv_key);
 	return (key->priv_key == NULL) ? 0 : 1;
 	}
 
 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
 	{
 	return key->pub_key;
 	}
 
 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
 	{
 	if (key->pub_key != NULL)
 		EC_POINT_free(key->pub_key);
 	key->pub_key = EC_POINT_dup(pub_key, key->group);
 	return (key->pub_key == NULL) ? 0 : 1;
 	}
 
 unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
 	{
 	return key->enc_flag;
 	}
 
 void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
 	{
 	key->enc_flag = flags;
 	}
 
 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
 	{
 	return key->conv_form;
 	}
 
 void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
 	{
 	key->conv_form = cform;
 	if (key->group != NULL)
 		EC_GROUP_set_point_conversion_form(key->group, cform);
 	}
 
 void *EC_KEY_get_key_method_data(EC_KEY *key,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	void *ret;
 
 	CRYPTO_r_lock(CRYPTO_LOCK_EC);
 	ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	CRYPTO_r_unlock(CRYPTO_LOCK_EC);
 
 	return ret;
 	}
 
 void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *ex_data;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_EC);
 	ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
 	if (ex_data == NULL)
 		EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
 	CRYPTO_w_unlock(CRYPTO_LOCK_EC);
 
 	return ex_data;
 	}
 
 void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
 	{
 	if (key->group != NULL)
 		EC_GROUP_set_asn1_flag(key->group, flag);
 	}
 
 int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
 	{
 	if (key->group == NULL)
 		return 0;
 	return EC_GROUP_precompute_mult(key->group, ctx);
 	}
Index: releng/9.3/crypto/openssl/crypto/ec/ec_lib.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ec_lib.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ec_lib.c	(revision 284295)
@@ -1,1164 +1,1172 @@
 /* crypto/ec/ec_lib.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Binary polynomial ECC support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #include 
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
 
 
 /* functions for EC_GROUP objects */
 
 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
 	{
 	EC_GROUP *ret;
 
 	if (meth == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	if (meth->group_init == 0)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = meth;
 
 	ret->extra_data = NULL;
 
 	ret->generator = NULL;
 	BN_init(&ret->order);
 	BN_init(&ret->cofactor);
 
 	ret->curve_name = 0;	
 	ret->asn1_flag  = 0;
 	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
 
 	ret->seed = NULL;
 	ret->seed_len = 0;
 
 	if (!meth->group_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_GROUP_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_free(group->generator);
 	BN_free(&group->order);
 	BN_free(&group->cofactor);
 
 	if (group->seed)
 		OPENSSL_free(group->seed);
 
 	OPENSSL_free(group);
 	}
  
 
 void EC_GROUP_clear_free(EC_GROUP *group)
 	{
 	if (!group) return;
 
 	if (group->meth->group_clear_finish != 0)
 		group->meth->group_clear_finish(group);
 	else if (group->meth->group_finish != 0)
 		group->meth->group_finish(group);
 
 	EC_EX_DATA_clear_free_all_data(&group->extra_data);
 
 	if (group->generator != NULL)
 		EC_POINT_clear_free(group->generator);
 	BN_clear_free(&group->order);
 	BN_clear_free(&group->cofactor);
 
 	if (group->seed)
 		{
 		OPENSSL_cleanse(group->seed, group->seed_len);
 		OPENSSL_free(group->seed);
 		}
 
 	OPENSSL_cleanse(group, sizeof *group);
 	OPENSSL_free(group);
 	}
 
 
 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (dest->meth->group_copy == 0)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	
 	EC_EX_DATA_free_all_data(&dest->extra_data);
 
 	for (d = src->extra_data; d != NULL; d = d->next)
 		{
 		void *t = d->dup_func(d->data);
 		
 		if (t == NULL)
 			return 0;
 		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
 			return 0;
 		}
 
 	if (src->generator != NULL)
 		{
 		if (dest->generator == NULL)
 			{
 			dest->generator = EC_POINT_new(dest);
 			if (dest->generator == NULL) return 0;
 			}
 		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
 		}
 	else
 		{
 		/* src->generator == NULL */
 		if (dest->generator != NULL)
 			{
 			EC_POINT_clear_free(dest->generator);
 			dest->generator = NULL;
 			}
 		}
 
 	if (!BN_copy(&dest->order, &src->order)) return 0;
 	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
 
 	dest->curve_name = src->curve_name;
 	dest->asn1_flag  = src->asn1_flag;
 	dest->asn1_form  = src->asn1_form;
 
 	if (src->seed)
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = OPENSSL_malloc(src->seed_len);
 		if (dest->seed == NULL)
 			return 0;
 		if (!memcpy(dest->seed, src->seed, src->seed_len))
 			return 0;
 		dest->seed_len = src->seed_len;
 		}
 	else
 		{
 		if (dest->seed)
 			OPENSSL_free(dest->seed);
 		dest->seed = NULL;
 		dest->seed_len = 0;
 		}
 	
 
 	return dest->meth->group_copy(dest, src);
 	}
 
 
 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
 	{
 	EC_GROUP *t = NULL;
 	int ok = 0;
 
 	if (a == NULL) return NULL;
 
 	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
 	if (!EC_GROUP_copy(t, a)) goto err;
 
 	ok = 1;
 
   err:	
 	if (!ok)
 		{
 		if (t) EC_GROUP_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
 	{
 	return group->meth;
 	}
 
 
 int EC_METHOD_get_field_type(const EC_METHOD *meth)
         {
         return meth->field_type;
         }
 
 
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
 	{
 	if (generator == NULL)
 		{
 		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
 		return 0   ;
 		}
 
 	if (group->generator == NULL)
 		{
 		group->generator = EC_POINT_new(group);
 		if (group->generator == NULL) return 0;
 		}
 	if (!EC_POINT_copy(group->generator, generator)) return 0;
 
 	if (order != NULL)
 		{ if (!BN_copy(&group->order, order)) return 0; }	
 	else
 		BN_zero(&group->order);
 
 	if (cofactor != NULL)
 		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }	
 	else
 		BN_zero(&group->cofactor);
 
 	return 1;
 	}
 
 
 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
 	{
 	return group->generator;
 	}
 
 
 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
 	{
 	if (!BN_copy(order, &group->order))
 		return 0;
 
 	return !BN_is_zero(order);
 	}
 
 
 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
 	{
 	if (!BN_copy(cofactor, &group->cofactor))
 		return 0;
 
 	return !BN_is_zero(&group->cofactor);
 	}
 
 
 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
 	{
 	group->curve_name = nid;
 	}
 
 
 int EC_GROUP_get_curve_name(const EC_GROUP *group)
 	{
 	return group->curve_name;
 	}
 
 
 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
 	{
 	group->asn1_flag = flag;
 	}
 
 
 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
 	{
 	return group->asn1_flag;
 	}
 
 
 void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 
                                         point_conversion_form_t form)
 	{
 	group->asn1_form = form;
 	}
 
 
 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
 	{
 	return group->asn1_form;
 	}
 
 
 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
 	{
 	if (group->seed)
 		{
 		OPENSSL_free(group->seed);
 		group->seed = NULL;
 		group->seed_len = 0;
 		}
 
 	if (!len || !p)
 		return 1;
 
 	if ((group->seed = OPENSSL_malloc(len)) == NULL)
 		return 0;
 	memcpy(group->seed, p, len);
 	group->seed_len = len;
 
 	return len;
 	}
 
 
 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
 	{
 	return group->seed;
 	}
 
 
 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
 	{
 	return group->seed_len;
 	}
 
 
 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_set_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_set_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	if (group->meth->group_get_curve == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_curve(group, p, a, b, ctx);
 	}
 
 
 int EC_GROUP_get_degree(const EC_GROUP *group)
 	{
 	if (group->meth->group_get_degree == 0)
 		{
 		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_get_degree(group);
 	}
 
 
 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->group_check_discriminant == 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	return group->meth->group_check_discriminant(group, ctx);
 	}
 
 
 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
 	{
 	int    r = 0;
 	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
 	BN_CTX *ctx_new = NULL;
 
 	/* compare the field types*/
 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
 	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
 		return 1;
 	/* compare the curve name (if present in both) */
 	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
 	    EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
 		return 1;
 
 	if (!ctx)
 		ctx_new = ctx = BN_CTX_new();
 	if (!ctx)
 		return -1;
 	
 	BN_CTX_start(ctx);
 	a1 = BN_CTX_get(ctx);
 	a2 = BN_CTX_get(ctx);
 	a3 = BN_CTX_get(ctx);
 	b1 = BN_CTX_get(ctx);
 	b2 = BN_CTX_get(ctx);
 	b3 = BN_CTX_get(ctx);
 	if (!b3)
 		{
 		BN_CTX_end(ctx);
 		if (ctx_new)
 			BN_CTX_free(ctx);
 		return -1;
 		}
 
 	/* XXX This approach assumes that the external representation
 	 * of curves over the same field type is the same.
 	 */
 	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
 	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
 		r = 1;
 
 	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
 		r = 1;
 
 	/* XXX EC_POINT_cmp() assumes that the methods are equal */
 	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
 	    EC_GROUP_get0_generator(b), ctx))
 		r = 1;
 
 	if (!r)
 		{
 		/* compare the order and cofactor */
 		if (!EC_GROUP_get_order(a, a1, ctx) ||
 		    !EC_GROUP_get_order(b, b1, ctx) ||
 		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
 		    !EC_GROUP_get_cofactor(b, b2, ctx))
 			{
 			BN_CTX_end(ctx);
 			if (ctx_new)
 				BN_CTX_free(ctx);
 			return -1;
 			}
 		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
 			r = 1;
 		}
 
 	BN_CTX_end(ctx);
 	if (ctx_new)
 		BN_CTX_free(ctx);
 
 	return r;
 	}
 
 
 /* this has 'package' visibility */
 int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return 0;
 
 	for (d = *ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			{
 			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
 			return 0;
 			}
 		}
 
 	if (data == NULL)
 		/* no explicit entry needed */
 		return 1;
 
 	d = OPENSSL_malloc(sizeof *d);
 	if (d == NULL)
 		return 0;
 
 	d->data = data;
 	d->dup_func = dup_func;
 	d->free_func = free_func;
 	d->clear_free_func = clear_free_func;
 
 	d->next = *ex_data;
 	*ex_data = d;
 
 	return 1;
 	}
 
 /* this has 'package' visibility */
 void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	const EC_EXTRA_DATA *d;
 
 	for (d = ex_data; d != NULL; d = d->next)
 		{
 		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
 			return d->data;
 		}
 	
 	return NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
 	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
 	{
 	EC_EXTRA_DATA **p;
 
 	if (ex_data == NULL)
 		return;
 
 	for (p = ex_data; *p != NULL; p = &((*p)->next))
 		{
 		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
 			{
 			EC_EXTRA_DATA *next = (*p)->next;
 
 			(*p)->clear_free_func((*p)->data);
 			OPENSSL_free(*p);
 			
 			*p = next;
 			return;
 			}
 		}
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 /* this has 'package' visibility */
 void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
 	{
 	EC_EXTRA_DATA *d;
 
 	if (ex_data == NULL)
 		return;
 
 	d = *ex_data;
 	while (d)
 		{
 		EC_EXTRA_DATA *next = d->next;
 		
 		d->clear_free_func(d->data);
 		OPENSSL_free(d);
 		
 		d = next;
 		}
 	*ex_data = NULL;
 	}
 
 
 /* functions for EC_POINT objects */
 
 EC_POINT *EC_POINT_new(const EC_GROUP *group)
 	{
 	EC_POINT *ret;
 
 	if (group == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 		}
 	if (group->meth->point_init == 0)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return NULL;
 		}
 
 	ret = OPENSSL_malloc(sizeof *ret);
 	if (ret == NULL)
 		{
 		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 
 	ret->meth = group->meth;
 	
 	if (!ret->meth->point_init(ret))
 		{
 		OPENSSL_free(ret);
 		return NULL;
 		}
 	
 	return ret;
 	}
 
 
 void EC_POINT_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_free(point);
 	}
  
 
 void EC_POINT_clear_free(EC_POINT *point)
 	{
 	if (!point) return;
 
 	if (point->meth->point_clear_finish != 0)
 		point->meth->point_clear_finish(point);
 	else if (point->meth != NULL && point->meth->point_finish != 0)
 		point->meth->point_finish(point);
 	OPENSSL_cleanse(point, sizeof *point);
 	OPENSSL_free(point);
 	}
 
 
 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (dest->meth->point_copy == 0)
 		{
 		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (dest->meth != src->meth)
 		{
 		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	if (dest == src)
 		return 1;
 	return dest->meth->point_copy(dest, src);
 	}
 
 
 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
 	{
 	EC_POINT *t;
 	int r;
 
 	if (a == NULL) return NULL;
 
 	t = EC_POINT_new(group);
 	if (t == NULL) return(NULL);
 	r = EC_POINT_copy(t, a);
 	if (!r)
 		{
 		EC_POINT_free(t);
 		return NULL;
 		}
 	else return t;
 	}
 
 
 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
 	{
 	return point->meth;
 	}
 
 
 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	if (group->meth->point_set_to_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_to_infinity(group, point);
 	}
 
 
 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
 	}
 
 
 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	if (group->meth->point_get_affine_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
 	}
 
 
 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, int y_bit, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_compressed_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
 	}
 
 
 int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, int y_bit, BN_CTX *ctx)
 	{
 	if (group->meth->point_set_compressed_coordinates == 0)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
 	}
 
 
 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
         unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	if (group->meth->point2oct == 0)
 		{
 		ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->point2oct(group, point, form, buf, len, ctx);
 	}
 
 
 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
         const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	if (group->meth->oct2point == 0)
 		{
 		ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->oct2point(group, point, buf, len, ctx);
 	}
 
 
 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->add == 0)
 		{
 		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->add(group, r, a, b, ctx);
 	}
 
 
 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->dbl == 0)
 		{
 		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if ((group->meth != r->meth) || (r->meth != a->meth))
 		{
 		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->dbl(group, r, a, ctx);
 	}
 
 
 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
 	{
 	if (group->meth->invert == 0)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != a->meth)
 		{
 		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->invert(group, a, ctx);
 	}
 
 
 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	if (group->meth->is_at_infinity == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_at_infinity(group, point);
 	}
 
 
-int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+/*
+ * Check whether an EC_POINT is on the curve or not. Note that the return
+ * value for this function should NOT be treated as a boolean. Return values:
+ *  1: The point is on the curve
+ *  0: The point is not on the curve
+ * -1: An error occurred
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+                         BN_CTX *ctx)
 	{
 	if (group->meth->is_on_curve == 0)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->is_on_curve(group, point, ctx);
 	}
 
 
 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	if (group->meth->point_cmp == 0)
 		{
 		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return -1;
 		}
 	if ((group->meth != a->meth) || (a->meth != b->meth))
 		{
 		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
 		return -1;
 		}
 	return group->meth->point_cmp(group, a, b, ctx);
 	}
 
 
 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (group->meth->make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	if (group->meth != point->meth)
 		{
 		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
 	return group->meth->make_affine(group, point, ctx);
 	}
 
 
 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	size_t i;
 
 	if (group->meth->points_make_affine == 0)
 		{
 		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 		return 0;
 		}
 	for (i = 0; i < num; i++)
 		{
 		if (group->meth != points[i]->meth)
 			{
 			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
 			return 0;
 			}
 		}
 	return group->meth->points_make_affine(group, num, points, ctx);
 	}
 
 
 /* Functions for point multiplication.
  *
  * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
  * otherwise we dispatch through methods.
  */
 
 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
 	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
 
 	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
 	}
 
 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
 	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
 	{
 	/* just a convenient interface to EC_POINTs_mul() */
 
 	const EC_POINT *points[1];
 	const BIGNUM *scalars[1];
 
 	points[0] = point;
 	scalars[0] = p_scalar;
 
 	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
 	}
 
 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_precompute_mult(group, ctx);
 
 	if (group->meth->precompute_mult != 0)
 		return group->meth->precompute_mult(group, ctx);
 	else
 		return 1; /* nothing to do, so report success */
 	}
 
 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
 	{
 	if (group->meth->mul == 0)
 		/* use default */
 		return ec_wNAF_have_precompute_mult(group);
 
 	if (group->meth->have_precompute_mult != 0)
 		return group->meth->have_precompute_mult(group);
 	else
 		return 0; /* cannot tell whether precomputation has been performed */
 	}
Index: releng/9.3/crypto/openssl/crypto/ec/ecp_smpl.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ecp_smpl.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ecp_smpl.c	(revision 284295)
@@ -1,1697 +1,1698 @@
 /* crypto/ec/ecp_smpl.c */
 /* Includes code written by Lenka Fibikova 
  * for the OpenSSL project. 
  * Includes code written by Bodo Moeller for the OpenSSL project.
 */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
  * and contributed to the OpenSSL project.
  */
 
 #include 
 #include 
 
 #include "ec_lcl.h"
 
 const EC_METHOD *EC_GFp_simple_method(void)
 	{
 	static const EC_METHOD ret = {
 		NID_X9_62_prime_field,
 		ec_GFp_simple_group_init,
 		ec_GFp_simple_group_finish,
 		ec_GFp_simple_group_clear_finish,
 		ec_GFp_simple_group_copy,
 		ec_GFp_simple_group_set_curve,
 		ec_GFp_simple_group_get_curve,
 		ec_GFp_simple_group_get_degree,
 		ec_GFp_simple_group_check_discriminant,
 		ec_GFp_simple_point_init,
 		ec_GFp_simple_point_finish,
 		ec_GFp_simple_point_clear_finish,
 		ec_GFp_simple_point_copy,
 		ec_GFp_simple_point_set_to_infinity,
 		ec_GFp_simple_set_Jprojective_coordinates_GFp,
 		ec_GFp_simple_get_Jprojective_coordinates_GFp,
 		ec_GFp_simple_point_set_affine_coordinates,
 		ec_GFp_simple_point_get_affine_coordinates,
 		ec_GFp_simple_set_compressed_coordinates,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		ec_GFp_simple_add,
 		ec_GFp_simple_dbl,
 		ec_GFp_simple_invert,
 		ec_GFp_simple_is_at_infinity,
 		ec_GFp_simple_is_on_curve,
 		ec_GFp_simple_cmp,
 		ec_GFp_simple_make_affine,
 		ec_GFp_simple_points_make_affine,
 		0 /* mul */,
 		0 /* precompute_mult */,
 		0 /* have_precompute_mult */,	
 		ec_GFp_simple_field_mul,
 		ec_GFp_simple_field_sqr,
 		0 /* field_div */,
 		0 /* field_encode */,
 		0 /* field_decode */,
 		0 /* field_set_to_one */ };
 
 	return &ret;
 	}
 
 
 /* Most method functions in this file are designed to work with
  * non-trivial representations of field elements if necessary
  * (see ecp_mont.c): while standard modular addition and subtraction
  * are used, the field_mul and field_sqr methods will be used for
  * multiplication, and field_encode and field_decode (if defined)
  * will be used for converting between representations.
 
  * Functions ec_GFp_simple_points_make_affine() and
  * ec_GFp_simple_point_get_affine_coordinates() specifically assume
  * that if a non-trivial representation is used, it is a Montgomery
  * representation (i.e. 'encoding' means multiplying by some factor R).
  */
 
 
 int ec_GFp_simple_group_init(EC_GROUP *group)
 	{
 	BN_init(&group->field);
 	BN_init(&group->a);
 	BN_init(&group->b);
 	group->a_is_minus3 = 0;
 	return 1;
 	}
 
 
 void ec_GFp_simple_group_finish(EC_GROUP *group)
 	{
 	BN_free(&group->field);
 	BN_free(&group->a);
 	BN_free(&group->b);
 	}
 
 
 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
 	{
 	BN_clear_free(&group->field);
 	BN_clear_free(&group->a);
 	BN_clear_free(&group->b);
 	}
 
 
 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
 	{
 	if (!BN_copy(&dest->field, &src->field)) return 0;
 	if (!BN_copy(&dest->a, &src->a)) return 0;
 	if (!BN_copy(&dest->b, &src->b)) return 0;
 
 	dest->a_is_minus3 = src->a_is_minus3;
 
 	return 1;
 	}
 
 
 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp_a;
 	
 	/* p must be a prime > 3 */
 	if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	tmp_a = BN_CTX_get(ctx);
 	if (tmp_a == NULL) goto err;
 
 	/* group->field */
 	if (!BN_copy(&group->field, p)) goto err;
 	BN_set_negative(&group->field, 0);
 
 	/* group->a */
 	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
 	if (group->meth->field_encode)
 		{ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }	
 	else
 		if (!BN_copy(&group->a, tmp_a)) goto err;
 	
 	/* group->b */
 	if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
 	if (group->meth->field_encode)
 		if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
 	
 	/* group->a_is_minus3 */
 	if (!BN_add_word(tmp_a, 3)) goto err;
 	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BN_CTX *new_ctx = NULL;
 	
 	if (p != NULL)
 		{
 		if (!BN_copy(p, &group->field)) return 0;
 		}
 
 	if (a != NULL || b != NULL)
 		{
 		if (group->meth->field_decode)
 			{
 			if (ctx == NULL)
 				{
 				ctx = new_ctx = BN_CTX_new();
 				if (ctx == NULL)
 					return 0;
 				}
 			if (a != NULL)
 				{
 				if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
 				}
 			if (b != NULL)
 				{
 				if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
 				}
 			}
 		else
 			{
 			if (a != NULL)
 				{
 				if (!BN_copy(a, &group->a)) goto err;
 				}
 			if (b != NULL)
 				{
 				if (!BN_copy(b, &group->b)) goto err;
 				}
 			}
 		}
 	
 	ret = 1;
 	
  err:
 	if (new_ctx)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
 	{
 	return BN_num_bits(&group->field);
 	}
 
 
 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
 	{
 	int ret = 0;
 	BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
 	const BIGNUM *p = &group->field;
 	BN_CTX *new_ctx = NULL;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	BN_CTX_start(ctx);
 	a = BN_CTX_get(ctx);
 	b = BN_CTX_get(ctx);
 	tmp_1 = BN_CTX_get(ctx);
 	tmp_2 = BN_CTX_get(ctx);
 	order = BN_CTX_get(ctx);
 	if (order == NULL) goto err;
 
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
 		if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_copy(a, &group->a)) goto err;
 		if (!BN_copy(b, &group->b)) goto err;
 		}
 	
 	/* check the discriminant:
 	 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) 
          * 0 =< a, b < p */
 	if (BN_is_zero(a))
 		{
 		if (BN_is_zero(b)) goto err;
 		}
 	else if (!BN_is_zero(b))
 		{
 		if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
 		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
 		if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
 		/* tmp_1 = 4*a^3 */
 
 		if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
 		if (!BN_mul_word(tmp_2, 27)) goto err;
 		/* tmp_2 = 27*b^2 */
 
 		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
 		if (BN_is_zero(a)) goto err;
 		}
 	ret = 1;
 
 err:
 	if (ctx != NULL)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_point_init(EC_POINT *point)
 	{
 	BN_init(&point->X);
 	BN_init(&point->Y);
 	BN_init(&point->Z);
 	point->Z_is_one = 0;
 
 	return 1;
 	}
 
 
 void ec_GFp_simple_point_finish(EC_POINT *point)
 	{
 	BN_free(&point->X);
 	BN_free(&point->Y);
 	BN_free(&point->Z);
 	}
 
 
 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
 	{
 	BN_clear_free(&point->X);
 	BN_clear_free(&point->Y);
 	BN_clear_free(&point->Z);
 	point->Z_is_one = 0;
 	}
 
 
 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
 	{
 	if (!BN_copy(&dest->X, &src->X)) return 0;
 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
 	dest->Z_is_one = src->Z_is_one;
 
 	return 1;
 	}
 
 
 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
 	{
 	point->Z_is_one = 0;
 	BN_zero(&point->Z);
 	return 1;
 	}
 
 
 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	int ret = 0;
 	
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	if (x != NULL)
 		{
 		if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
 		if (group->meth->field_encode)
 			{
 			if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
 			}
 		}
 	
 	if (y != NULL)
 		{
 		if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
 		if (group->meth->field_encode)
 			{
 			if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
 			}
 		}
 	
 	if (z != NULL)
 		{
 		int Z_is_one;
 
 		if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
 		Z_is_one = BN_is_one(&point->Z);
 		if (group->meth->field_encode)
 			{
 			if (Z_is_one && (group->meth->field_set_to_one != 0))
 				{
 				if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
 				}
 			else
 				{
 				if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
 				}
 			}
 		point->Z_is_one = Z_is_one;
 		}
 	
 	ret = 1;
 	
  err:
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	int ret = 0;
 	
 	if (group->meth->field_decode != 0)
 		{
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		if (x != NULL)
 			{
 			if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
 			}
 		if (y != NULL)
 			{
 			if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
 			}
 		if (z != NULL)
 			{
 			if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
 			}
 		}
 	else	
 		{
 		if (x != NULL)
 			{
 			if (!BN_copy(x, &point->X)) goto err;
 			}
 		if (y != NULL)
 			{
 			if (!BN_copy(y, &point->Y)) goto err;
 			}
 		if (z != NULL)
 			{
 			if (!BN_copy(z, &point->Z)) goto err;
 			}
 		}
 	
 	ret = 1;
 
  err:
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
 	if (x == NULL || y == NULL)
 		{
 		/* unlike for projective coordinates, we do not tolerate this */
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
 
 	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
 	}
 
 
 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
 	const BIGNUM *Z_;
 	int ret = 0;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	Z = BN_CTX_get(ctx);
 	Z_1 = BN_CTX_get(ctx);
 	Z_2 = BN_CTX_get(ctx);
 	Z_3 = BN_CTX_get(ctx);
 	if (Z_3 == NULL) goto err;
 
 	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
 	
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
 		Z_ = Z;
 		}
 	else
 		{
 		Z_ = &point->Z;
 		}
 	
 	if (BN_is_one(Z_))
 		{
 		if (group->meth->field_decode)
 			{
 			if (x != NULL)
 				{
 				if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
 				}
 			if (y != NULL)
 				{
 				if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
 				}
 			}
 		else
 			{
 			if (x != NULL)
 				{
 				if (!BN_copy(x, &point->X)) goto err;
 				}
 			if (y != NULL)
 				{
 				if (!BN_copy(y, &point->Y)) goto err;
 				}
 			}
 		}
 	else
 		{
 		if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
 			goto err;
 			}
 		
 		if (group->meth->field_encode == 0)
 			{
 			/* field_sqr works on standard representation */
 			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
 			}
 	
 		if (x != NULL)
 			{
 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
 			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
 			}
 
 		if (y != NULL)
 			{
 			if (group->meth->field_encode == 0)
 				{
 				/* field_mul works on standard representation */
 				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
 				}
 			else
 				{
 				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
 				}
 
 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
 			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
 			}
 		}
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp1, *tmp2, *x, *y;
 	int ret = 0;
 
 	/* clear error queue*/
 	ERR_clear_error();
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	y_bit = (y_bit != 0);
 
 	BN_CTX_start(ctx);
 	tmp1 = BN_CTX_get(ctx);
 	tmp2 = BN_CTX_get(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	/* Recover y.  We have a Weierstrass equation
 	 *     y^2 = x^3 + a*x + b,
 	 * so  y  is one of the square roots of  x^3 + a*x + b.
 	 */
 
 	/* tmp1 := x^3 */
 	if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
 	if (group->meth->field_decode == 0)
 		{
 		/* field_{sqr,mul} work on standard representation */
 		if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
 		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
 		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + a*x */
 	if (group->a_is_minus3)
 		{
 		if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
 		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
 		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (group->meth->field_decode)
 			{
 			if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
 			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
 			}
 		else
 			{
 			/* field_mul works on standard representation */
 			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
 			}
 		
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	
 	/* tmp1 := tmp1 + b */
 	if (group->meth->field_decode)
 		{
 		if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
 		}
 	else
 		{
 		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
 		}
 	
 	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
 		{
 		unsigned long err = ERR_peek_last_error();
 		
 		if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
 			{
 			ERR_clear_error();
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			}
 		else
 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
 		goto err;
 		}
 
 	if (y_bit != BN_is_odd(y))
 		{
 		if (BN_is_zero(y))
 			{
 			int kron;
 
 			kron = BN_kronecker(x, &group->field, ctx);
 			if (kron == -2) goto err;
 
 			if (kron == 1)
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
 			else
 				/* BN_mod_sqrt() should have cought this error (not a square) */
 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
 			goto err;
 			}
 		if (!BN_usub(y, &group->field, y)) goto err;
 		}
 	if (y_bit != BN_is_odd(y))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
 	unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	size_t ret;
 	BN_CTX *new_ctx = NULL;
 	int used_ctx = 0;
 	BIGNUM *x, *y;
 	size_t field_len, i, skip;
 
 	if ((form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
 		goto err;
 		}
 
 	if (EC_POINT_is_at_infinity(group, point))
 		{
 		/* encodes to a single 0 octet */
 		if (buf != NULL)
 			{
 			if (len < 1)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 				return 0;
 				}
 			buf[0] = 0;
 			}
 		return 1;
 		}
 
 
 	/* ret := required output buffer length */
 	field_len = BN_num_bytes(&group->field);
 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	/* if 'buf' is NULL, just return required length */
 	if (buf != NULL)
 		{
 		if (len < ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
 			goto err;
 			}
 
 		if (ctx == NULL)
 			{
 			ctx = new_ctx = BN_CTX_new();
 			if (ctx == NULL)
 				return 0;
 			}
 
 		BN_CTX_start(ctx);
 		used_ctx = 1;
 		x = BN_CTX_get(ctx);
 		y = BN_CTX_get(ctx);
 		if (y == NULL) goto err;
 
 		if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 
 		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
 			buf[0] = form + 1;
 		else
 			buf[0] = form;
 	
 		i = 1;
 		
 		skip = field_len - BN_num_bytes(x);
 		if (skip > field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		while (skip > 0)
 			{
 			buf[i++] = 0;
 			skip--;
 			}
 		skip = BN_bn2bin(x, buf + i);
 		i += skip;
 		if (i != 1 + field_len)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 
 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
 			{
 			skip = field_len - BN_num_bytes(y);
 			if (skip > field_len)
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			while (skip > 0)
 				{
 				buf[i++] = 0;
 				skip--;
 				}
 			skip = BN_bn2bin(y, buf + i);
 			i += skip;
 			}
 
 		if (i != ret)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 
  err:
 	if (used_ctx)
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return 0;
 	}
 
 
 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
 	const unsigned char *buf, size_t len, BN_CTX *ctx)
 	{
 	point_conversion_form_t form;
 	int y_bit;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	size_t field_len, enc_len;
 	int ret = 0;
 
 	if (len == 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
 		return 0;
 		}
 	form = buf[0];
 	y_bit = form & 1;
 	form = form & ~1U;
 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
 		&& (form != POINT_CONVERSION_HYBRID))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (form == 0)
 		{
 		if (len != 1)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			return 0;
 			}
 
 		return EC_POINT_set_to_infinity(group, point);
 		}
 	
 	field_len = BN_num_bytes(&group->field);
 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
 
 	if (len != enc_len)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		return 0;
 		}
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
 	if (BN_ucmp(x, &group->field) >= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 		goto err;
 		}
 
 	if (form == POINT_CONVERSION_COMPRESSED)
 		{
 		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
 		}
 	else
 		{
 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
 		if (BN_ucmp(y, &group->field) >= 0)
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 			goto err;
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
 			if (y_bit != BN_is_odd(y))
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
 				}
 			}
 
 		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
 		}
 
 	ret = 1;
 	
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
 	int ret = 0;
 	
 	if (a == b)
 		return EC_POINT_dbl(group, r, a, ctx);
 	if (EC_POINT_is_at_infinity(group, a))
 		return EC_POINT_copy(r, b);
 	if (EC_POINT_is_at_infinity(group, b))
 		return EC_POINT_copy(r, a);
 	
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	n0 = BN_CTX_get(ctx);
 	n1 = BN_CTX_get(ctx);
 	n2 = BN_CTX_get(ctx);
 	n3 = BN_CTX_get(ctx);
 	n4 = BN_CTX_get(ctx);
 	n5 = BN_CTX_get(ctx);
 	n6 = BN_CTX_get(ctx);
 	if (n6 == NULL) goto end;
 
 	/* Note that in this function we must not read components of 'a' or 'b'
 	 * once we have written the corresponding components of 'r'.
 	 * ('r' might be one of 'a' or 'b'.)
 	 */
 
 	/* n1, n2 */
 	if (b->Z_is_one)
 		{
 		if (!BN_copy(n1, &a->X)) goto end;
 		if (!BN_copy(n2, &a->Y)) goto end;
 		/* n1 = X_a */
 		/* n2 = Y_a */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
 		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
 		/* n1 = X_a * Z_b^2 */
 
 		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
 		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
 		/* n2 = Y_a * Z_b^3 */
 		}
 
 	/* n3, n4 */
 	if (a->Z_is_one)
 		{
 		if (!BN_copy(n3, &b->X)) goto end;
 		if (!BN_copy(n4, &b->Y)) goto end;
 		/* n3 = X_b */
 		/* n4 = Y_b */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
 		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
 		/* n3 = X_b * Z_a^2 */
 
 		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
 		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
 		/* n4 = Y_b * Z_a^3 */
 		}
 
 	/* n5, n6 */
 	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
 	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
 	/* n5 = n1 - n3 */
 	/* n6 = n2 - n4 */
 
 	if (BN_is_zero(n5))
 		{
 		if (BN_is_zero(n6))
 			{
 			/* a is the same point as b */
 			BN_CTX_end(ctx);
 			ret = EC_POINT_dbl(group, r, a, ctx);
 			ctx = NULL;
 			goto end;
 			}
 		else
 			{
 			/* a is the inverse of b */
 			BN_zero(&r->Z);
 			r->Z_is_one = 0;
 			ret = 1;
 			goto end;
 			}
 		}
 
 	/* 'n7', 'n8' */
 	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
 	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
 	/* 'n7' = n1 + n3 */
 	/* 'n8' = n2 + n4 */
 
 	/* Z_r */
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		if (!BN_copy(&r->Z, n5)) goto end;
 		}
 	else
 		{
 		if (a->Z_is_one)
 			{ if (!BN_copy(n0, &b->Z)) goto end; }
 		else if (b->Z_is_one)
 			{ if (!BN_copy(n0, &a->Z)) goto end; }
 		else
 			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
 		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
 		}
 	r->Z_is_one = 0;
 	/* Z_r = Z_a * Z_b * n5 */
 
 	/* X_r */
 	if (!field_sqr(group, n0, n6, ctx)) goto end;
 	if (!field_sqr(group, n4, n5, ctx)) goto end;
 	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
 	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
 	/* X_r = n6^2 - n5^2 * 'n7' */
 	
 	/* 'n9' */
 	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
 	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
 	/* n9 = n5^2 * 'n7' - 2 * X_r */
 
 	/* Y_r */
 	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
 	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
 	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
 	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
 	if (BN_is_odd(n0))
 		if (!BN_add(n0, n0, p)) goto end;
 	/* now  0 <= n0 < 2*p,  and n0 is even */
 	if (!BN_rshift1(&r->Y, n0)) goto end;
 	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
 
 	ret = 1;
 
  end:
 	if (ctx) /* otherwise we already called BN_CTX_end */
 		BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *n0, *n1, *n2, *n3;
 	int ret = 0;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		BN_zero(&r->Z);
 		r->Z_is_one = 0;
 		return 1;
 		}
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	n0 = BN_CTX_get(ctx);
 	n1 = BN_CTX_get(ctx);
 	n2 = BN_CTX_get(ctx);
 	n3 = BN_CTX_get(ctx);
 	if (n3 == NULL) goto err;
 
 	/* Note that in this function we must not read components of 'a'
 	 * once we have written the corresponding components of 'r'.
 	 * ('r' might the same as 'a'.)
 	 */
 
 	/* n1 */
 	if (a->Z_is_one)
 		{
 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
 		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
 		/* n1 = 3 * X_a^2 + a_curve */
 		}
 	else if (group->a_is_minus3)
 		{
 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
 		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
 		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
 		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
 		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
 		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
 		 *    = 3 * X_a^2 - 3 * Z_a^4 */
 		}
 	else
 		{
 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
 		if (!field_sqr(group, n1, n1, ctx)) goto err;
 		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
 		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
 		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
 		}
 
 	/* Z_r */
 	if (a->Z_is_one)
 		{
 		if (!BN_copy(n0, &a->Y)) goto err;
 		}
 	else
 		{
 		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
 		}
 	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
 	r->Z_is_one = 0;
 	/* Z_r = 2 * Y_a * Z_a */
 
 	/* n2 */
 	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
 	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
 	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
 	/* n2 = 4 * X_a * Y_a^2 */
 
 	/* X_r */
 	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
 	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
 	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
 	/* X_r = n1^2 - 2 * n2 */
 	
 	/* n3 */
 	if (!field_sqr(group, n0, n3, ctx)) goto err;
 	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
 	/* n3 = 8 * Y_a^4 */
 	
 	/* Y_r */
 	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
 	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
 	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
 	/* Y_r = n1 * (n2 - X_r) - n3 */
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
 		/* point is its own inverse */
 		return 1;
 	
 	return BN_usub(&point->Y, &group->field, &point->Y);
 	}
 
 
 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	return BN_is_zero(&point->Z);
 	}
 
 
 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
 	{
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	const BIGNUM *p;
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *rh, *tmp, *Z4, *Z6;
 	int ret = -1;
 
 	if (EC_POINT_is_at_infinity(group, point))
 		return 1;
 	
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 	p = &group->field;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	rh = BN_CTX_get(ctx);
 	tmp = BN_CTX_get(ctx);
 	Z4 = BN_CTX_get(ctx);
 	Z6 = BN_CTX_get(ctx);
 	if (Z6 == NULL) goto err;
 
 	/* We have a curve defined by a Weierstrass equation
 	 *      y^2 = x^3 + a*x + b.
 	 * The point to consider is given in Jacobian projective coordinates
 	 * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
 	 * Substituting this and multiplying by  Z^6  transforms the above equation into
 	 *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
 	 * To test this, we add up the right-hand side in 'rh'.
 	 */
 
 	/* rh := X^2 */
 	if (!field_sqr(group, rh, &point->X, ctx)) goto err;
 
 	if (!point->Z_is_one)
 		{
 		if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
 		if (!field_sqr(group, Z4, tmp, ctx)) goto err;
 		if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
 
 		/* rh := (rh + a*Z^4)*X */
 		if (group->a_is_minus3)
 			{
 			if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
 			if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
 			if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 			}
 		else
 			{
 			if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
 			if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 			}
 
 		/* rh := rh + b*Z^6 */
 		if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
 		if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
 		}
 	else
 		{
 		/* point->Z_is_one */
 
 		/* rh := (rh + a)*X */
 		if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
 		if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 		/* rh := rh + b */
 		if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
 		}
 
 	/* 'lh' := Y^2 */
 	if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
 
 	ret = (0 == BN_ucmp(tmp, rh));
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
 	{
 	/* return values:
 	 *  -1   error
 	 *   0   equal (in affine coordinates)
 	 *   1   not equal
 	 */
 
 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
 	const BIGNUM *tmp1_, *tmp2_;
 	int ret = -1;
 	
 	if (EC_POINT_is_at_infinity(group, a))
 		{
 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
 		}
 
 	if (EC_POINT_is_at_infinity(group, b))
 		return 1;
 	
 	if (a->Z_is_one && b->Z_is_one)
 		{
 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
 		}
 
 	field_mul = group->meth->field_mul;
 	field_sqr = group->meth->field_sqr;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return -1;
 		}
 
 	BN_CTX_start(ctx);
 	tmp1 = BN_CTX_get(ctx);
 	tmp2 = BN_CTX_get(ctx);
 	Za23 = BN_CTX_get(ctx);
 	Zb23 = BN_CTX_get(ctx);
 	if (Zb23 == NULL) goto end;
 
 	/* We have to decide whether
 	 *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
 	 * or equivalently, whether
 	 *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
 	 */
 
 	if (!b->Z_is_one)
 		{
 		if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
 		if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
 		tmp1_ = tmp1;
 		}
 	else
 		tmp1_ = &a->X;
 	if (!a->Z_is_one)
 		{
 		if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
 		if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
 		tmp2_ = tmp2;
 		}
 	else
 		tmp2_ = &b->X;
 	
 	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
 	if (BN_cmp(tmp1_, tmp2_) != 0)
 		{
 		ret = 1; /* points differ */
 		goto end;
 		}
 
 
 	if (!b->Z_is_one)
 		{
 		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
 		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
 		/* tmp1_ = tmp1 */
 		}
 	else
 		tmp1_ = &a->Y;
 	if (!a->Z_is_one)
 		{
 		if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
 		if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
 		/* tmp2_ = tmp2 */
 		}
 	else
 		tmp2_ = &b->Y;
 
 	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
 	if (BN_cmp(tmp1_, tmp2_) != 0)
 		{
 		ret = 1; /* points differ */
 		goto end;
 		}
 
 	/* points are equal */
 	ret = 0;
 
  end:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *x, *y;
 	int ret = 0;
 
 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
 		return 1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	x = BN_CTX_get(ctx);
 	y = BN_CTX_get(ctx);
 	if (y == NULL) goto err;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 	if (!point->Z_is_one)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 	
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	return ret;
 	}
 
 
 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;
 	BIGNUM *tmp, *tmp_Z;
 	BIGNUM **prod_Z = NULL;
 	size_t i;
 	int ret = 0;
 
 	if (num == 0)
 		return 1;
 
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
 		if (ctx == NULL)
 			return 0;
 		}
 
 	BN_CTX_start(ctx);
 	tmp = BN_CTX_get(ctx);
 	tmp_Z = BN_CTX_get(ctx);
 	if (tmp == NULL || tmp_Z == NULL) goto err;
 
 	prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]);
 	if (prod_Z == NULL) goto err;
 	for (i = 0; i < num; i++)
 		{
 		prod_Z[i] = BN_new();
 		if (prod_Z[i] == NULL) goto err;
 		}
 
 	/* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
 	 * skipping any zero-valued inputs (pretend that they're 1). */
 
 	if (!BN_is_zero(&points[0]->Z))
 		{
 		if (!BN_copy(prod_Z[0], &points[0]->Z)) goto err;
 		}
 	else
 		{
 		if (group->meth->field_set_to_one != 0)
 			{
 			if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_one(prod_Z[0])) goto err;
 			}
 		}
 
 	for (i = 1; i < num; i++)
 		{
 		if (!BN_is_zero(&points[i]->Z))
 			{
 			if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) goto err;
 			}
 		else
 			{
 			if (!BN_copy(prod_Z[i], prod_Z[i - 1])) goto err;
 			}
 		}
 
 	/* Now use a single explicit inversion to replace every
 	 * non-zero points[i]->Z by its inverse. */
 
 	if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx))
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
 		goto err;
 		}
 	if (group->meth->field_encode != 0)
 		{
 		/* In the Montgomery case, we just turned  R*H  (representing H)
 		 * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
 		 * i.e. we need to multiply by the Montgomery factor twice. */
 		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
 		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
 		}
 
 	for (i = num - 1; i > 0; --i)
 		{
 		/* Loop invariant: tmp is the product of the inverses of
 		 * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
 		if (!BN_is_zero(&points[i]->Z))
 			{
 			/* Set tmp_Z to the inverse of points[i]->Z (as product
 			 * of Z inverses 0 .. i, Z values 0 .. i - 1). */
 			if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) goto err;
 			/* Update tmp to satisfy the loop invariant for i - 1. */
 			if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) goto err;
 			/* Replace points[i]->Z by its inverse. */
 			if (!BN_copy(&points[i]->Z, tmp_Z)) goto err;
 			}
 		}
 
 	if (!BN_is_zero(&points[0]->Z))
 		{
 		/* Replace points[0]->Z by its inverse. */
 		if (!BN_copy(&points[0]->Z, tmp)) goto err;
 		}
 
 	/* Finally, fix up the X and Y coordinates for all points. */
 
 	for (i = 0; i < num; i++)
 		{
 		EC_POINT *p = points[i];
 
 		if (!BN_is_zero(&p->Z))
 			{
 			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
 
 			if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) goto err;
 			if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) goto err;
 
 			if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) goto err;
 			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) goto err;
 
 			if (group->meth->field_set_to_one != 0)
 				{
 				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
 				}
 			else
 				{
 				if (!BN_one(&p->Z)) goto err;
 				}
 			p->Z_is_one = 1;
 			}
 		}
 
 	ret = 1;
 
  err:
 	BN_CTX_end(ctx);
 	if (new_ctx != NULL)
 		BN_CTX_free(new_ctx);
 	if (prod_Z != NULL)
 		{
 		for (i = 0; i < num; i++)
 			{
 			if (prod_Z[i] == NULL) break;
 			BN_clear_free(prod_Z[i]);
 			}
 		OPENSSL_free(prod_Z);
 		}
 	return ret;
 	}
 
 
 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	return BN_mod_mul(r, a, b, &group->field, ctx);
 	}
 
 
 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
 	{
 	return BN_mod_sqr(r, a, &group->field, ctx);
 	}
Index: releng/9.3/crypto/openssl/crypto/ec/ectest.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/ec/ectest.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/ec/ectest.c	(revision 284295)
@@ -1,1344 +1,1344 @@
 /* crypto/ec/ectest.c */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * The elliptic curve binary polynomial software is originally written by 
  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
  *
  */
 
 #include 
 #include 
 #ifdef FLAT_INC
 #include "e_os.h"
 #else
 #include "../e_os.h"
 #endif
 #include 
 #include 
 
 
 #ifdef OPENSSL_NO_EC
 int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
 #else
 
 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include 
 #include 
 #include 
 #include 
 #include 
 
 #if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
 /* suppress "too big too optimize" warning */
 #pragma warning(disable:4959)
 #endif
 
 #define ABORT do { \
 	fflush(stdout); \
 	fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
 	ERR_print_errors_fp(stderr); \
 	EXIT(1); \
 } while (0)
 
 void prime_field_tests(void);
 void char2_field_tests(void);
 void internal_curve_test(void);
 
 #define TIMING_BASE_PT 0
 #define TIMING_RAND_PT 1
 #define TIMING_SIMUL 2
 
 #if 0
 static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
 	{
 	clock_t clck;
 	int i, j;
 	BIGNUM *s;
 	BIGNUM *r[10], *r0[10];
 	EC_POINT *P;
 		
 	s = BN_new();
 	if (s == NULL) ABORT;
 
 	fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
 	if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
 	fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
 	fflush(stdout);
 
 	P = EC_POINT_new(group);
 	if (P == NULL) ABORT;
 	EC_POINT_copy(P, EC_GROUP_get0_generator(group));
 
 	for (i = 0; i < 10; i++)
 		{
 		if ((r[i] = BN_new()) == NULL) ABORT;
 		if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
 		if (type != TIMING_BASE_PT)
 			{
 			if ((r0[i] = BN_new()) == NULL) ABORT;
 			if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
 			}
 		}
 
 	clck = clock();
 	for (i = 0; i < 10; i++)
 		{
 		for (j = 0; j < 10; j++)
 			{
 			if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, 
 				(type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
 			}
 		}
 	clck = clock() - clck;
 
 	fprintf(stdout, "\n");
 
 #ifdef CLOCKS_PER_SEC
 	/* "To determine the time in seconds, the value returned
 	 * by the clock function should be divided by the value
 	 * of the macro CLOCKS_PER_SEC."
 	 *                                       -- ISO/IEC 9899 */
 #	define UNIT "s"
 #else
 	/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
 	 *                            -- cc on NeXTstep/OpenStep */
 #	define UNIT "units"
 #	define CLOCKS_PER_SEC 1
 #endif
 
 	if (type == TIMING_BASE_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"base point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_RAND_PT) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"random point multiplications", (double)clck/CLOCKS_PER_SEC);
 	} else if (type == TIMING_SIMUL) {
 		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
 			"s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
 	}
 	fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
 
 	EC_POINT_free(P);
 	BN_free(s);
 	for (i = 0; i < 10; i++)
 		{
 		BN_free(r[i]);
 		if (type != TIMING_BASE_PT) BN_free(r0[i]);
 		}
 	}
 #endif
 
 void prime_field_tests()
 	{	
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "17")) ABORT;
 	if (!BN_hex2bn(&a, "1")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
 	                                             * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	if (!x || !y || !z) ABORT;
 
 	if (!BN_hex2bn(&x, "D")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 
 #if 0 /* optional */
 		{
 			EC_POINT *points[3];
 		
 			points[0] = R;
 			points[1] = Q;
 			points[2] = P;
 			if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
 		}
 #endif
 
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octect string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octect string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 	if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
 	fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, ", Y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, ", Z = 0x");
 	BN_print_fp(stdout, z);
 	fprintf(stdout, "\n");
 
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
 	 * -- not a NIST curve, but commonly used */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
 	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 160) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_160, group)) ABORT;
 
 
 	/* Curve P-192 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-192 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 192) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_192, group)) ABORT;
 
 
 	/* Curve P-224 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
 	if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-224 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 224) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_224, group)) ABORT;
 
 
 	/* Curve P-256 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
 		"84F3B9CAC2FC632551")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-256 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 256) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_256, group)) ABORT;
 
 
 	/* Curve P-384 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
 		"120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
 		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-384 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"
 		"7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 384) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_384, group)) ABORT;
 
 
 	/* Curve P-521 (FIPS PUB 186-2, App. 6) */
 	
 	if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
 	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
 	if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
 	if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"
 		"315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"
 		"DF883D2C34F1EF451FD46B503F00")) ABORT;
 	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
 
 	if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"
 		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
 		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
 		"C9B8899C47AEBB6FB71E91386409")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
 	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
 	fprintf(stdout, "\nNIST curve P-521 -- Generator:\n     x = 0x");
 	BN_print_fp(stdout, x);
 	fprintf(stdout, "\n     y = 0x");
 	BN_print_fp(stdout, y);
 	fprintf(stdout, "\n");
 	/* G_y value taken from the standard: */
 	if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"
 		"B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"
 		"7086A272C24088BE94769FD16650")) ABORT;
 	if (0 != BN_cmp(y, z)) ABORT;
 	
 	fprintf(stdout, "verify degree ...");
 	if (EC_GROUP_get_degree(group) != 521) ABORT;
 	fprintf(stdout, " ok\n");
 	
 	fprintf(stdout, "verify group order ...");
 	fflush(stdout);
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, ".");
 	fflush(stdout);
 #if 0
 	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
 #endif
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
 	fprintf(stdout, " ok\n");
 
 	if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
 	if (!EC_GROUP_copy(P_521, group)) ABORT;
 
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[4];
 		const BIGNUM *scalars[4];
 		BIGNUM scalar3;
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 		points[3] = Q;
 
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		BN_init(&scalar3);
 		BN_zero(&scalar3);
 		scalars[3] = &scalar3;
 
 		if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 
 		BN_free(&scalar3);
 	}
 
 
 #if 0
 	timings(P_160, TIMING_BASE_PT, ctx);
 	timings(P_160, TIMING_RAND_PT, ctx);
 	timings(P_160, TIMING_SIMUL, ctx);
 	timings(P_192, TIMING_BASE_PT, ctx);
 	timings(P_192, TIMING_RAND_PT, ctx);
 	timings(P_192, TIMING_SIMUL, ctx);
 	timings(P_224, TIMING_BASE_PT, ctx);
 	timings(P_224, TIMING_RAND_PT, ctx);
 	timings(P_224, TIMING_SIMUL, ctx);
 	timings(P_256, TIMING_BASE_PT, ctx);
 	timings(P_256, TIMING_RAND_PT, ctx);
 	timings(P_256, TIMING_SIMUL, ctx);
 	timings(P_384, TIMING_BASE_PT, ctx);
 	timings(P_384, TIMING_RAND_PT, ctx);
 	timings(P_384, TIMING_SIMUL, ctx);
 	timings(P_521, TIMING_BASE_PT, ctx);
 	timings(P_521, TIMING_RAND_PT, ctx);
 	timings(P_521, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z);
 
 	if (P_160) EC_GROUP_free(P_160);
 	if (P_192) EC_GROUP_free(P_192);
 	if (P_224) EC_GROUP_free(P_224);
 	if (P_256) EC_GROUP_free(P_256);
 	if (P_384) EC_GROUP_free(P_384);
 	if (P_521) EC_GROUP_free(P_521);
 
 	}
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n"); \
 	/* G_y value taken from the standard: */ \
 	if (!BN_hex2bn(&z, _y)) ABORT; \
 	if (0 != BN_cmp(y, z)) ABORT;
 #else 
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!BN_hex2bn(&y, _y)) ABORT; \
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
 	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
 	BN_print_fp(stdout, x); \
 	fprintf(stdout, "\n     y = 0x"); \
 	BN_print_fp(stdout, y); \
 	fprintf(stdout, "\n");
 #endif
 
 #define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&p, _p)) ABORT; \
 	if (!BN_hex2bn(&a, _a)) ABORT; \
 	if (!BN_hex2bn(&b, _b)) ABORT; \
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \
 	CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	fprintf(stdout, "verify degree ..."); \
 	if (EC_GROUP_get_degree(group) != _degree) ABORT; \
 	fprintf(stdout, " ok\n"); \
 	fprintf(stdout, "verify group order ..."); \
 	fflush(stdout); \
 	if (!EC_GROUP_get_order(group, z, ctx)) ABORT; \
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
 	fprintf(stdout, "."); \
 	fflush(stdout); \
 	/* if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; */ \
 	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
 	if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
 	fprintf(stdout, " ok\n"); \
 	if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
 	if (!EC_GROUP_copy(_variable, group)) ABORT;
 
 void char2_field_tests()
 	{	
 	BN_CTX *ctx = NULL;
 	BIGNUM *p, *a, *b;
 	EC_GROUP *group;
 	EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
 	EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
 	EC_POINT *P, *Q, *R;
 	BIGNUM *x, *y, *z, *cof;
 	unsigned char buf[100];
 	size_t i, len;
 	int k;
 	
 #if 1 /* optional */
 	ctx = BN_CTX_new();
 	if (!ctx) ABORT;
 #endif
 
 	p = BN_new();
 	a = BN_new();
 	b = BN_new();
 	if (!p || !a || !b) ABORT;
 
 	if (!BN_hex2bn(&p, "13")) ABORT;
 	if (!BN_hex2bn(&a, "3")) ABORT;
 	if (!BN_hex2bn(&b, "1")) ABORT;
 	
 	group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
 	                                                * so that the library gets to choose the EC_METHOD */
 	if (!group) ABORT;
 	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	{
 		EC_GROUP *tmp;
 		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
 		if (!tmp) ABORT;
 		if (!EC_GROUP_copy(tmp, group)) ABORT;
 		EC_GROUP_free(group);
 		group = tmp;
 	}
 	
 	if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;
 
 	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
 	BN_print_fp(stdout, p);
 	fprintf(stdout, ")\n     a = 0x");
 	BN_print_fp(stdout, a);
 	fprintf(stdout, "\n     b = 0x");
 	BN_print_fp(stdout, b);
 	fprintf(stdout, "\n(0x... means binary polynomial)\n");
 
 	P = EC_POINT_new(group);
 	Q = EC_POINT_new(group);
 	R = EC_POINT_new(group);
 	if (!P || !Q || !R) ABORT;
 	
 	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	buf[0] = 0;
 	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
 
 	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 	x = BN_new();
 	y = BN_new();
 	z = BN_new();
 	cof = BN_new();
 	if (!x || !y || !z || !cof) ABORT;
 
 	if (!BN_hex2bn(&x, "6")) ABORT;
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
 #else
 	if (!BN_hex2bn(&y, "8")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 		if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
 		fprintf(stderr, "Point is not on curve: x = 0x");
 		BN_print_fp(stderr, x);
 		fprintf(stderr, ", y = 0x");
 		BN_print_fp(stderr, y);
 		fprintf(stderr, "\n");
 		ABORT;
 		}
 
 	fprintf(stdout, "A cyclic subgroup:\n");
 	k = 100;
 	do
 		{
 		if (k-- == 0) ABORT;
 
 		if (EC_POINT_is_at_infinity(group, P))
 			fprintf(stdout, "     point at infinity\n");
 		else
 			{
 			if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;
 
 			fprintf(stdout, "     x = 0x");
 			BN_print_fp(stdout, x);
 			fprintf(stdout, ", y = 0x");
 			BN_print_fp(stdout, y);
 			fprintf(stdout, "\n");
 			}
 		
 		if (!EC_POINT_copy(R, P)) ABORT;
 		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
 		}
 	while (!EC_POINT_is_at_infinity(group, P));
 
 	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 	
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 	
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
 	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
 	if (len == 0) ABORT;
 	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
 	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
 	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
 #endif
 
 	fprintf(stdout, "\n");
 	
 	if (!EC_POINT_invert(group, P, ctx)) ABORT;
 	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 
 
 	/* Curve K-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"1",
 		"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
 		"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
 		1,
 		"04000000000000000000020108A2E0CC0D99F8A5EF",
 		"2",
 		163,
 		C2_K163
 		);
 
 	/* Curve B-163 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-163",
 		"0800000000000000000000000000000000000000C9",
 		"1",
 		"020A601907B8C953CA1481EB10512F78744A3205FD",
 		"03F0EBA16286A2D57EA0991168D4994637E8343E36",
 		"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
 		1,
 		"040000000000000000000292FE77E70C12A4234C33",
 		"2",
 		163,
 		C2_B163
 		);
 
 	/* Curve K-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"0",
 		"1",
 		"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
 		"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
 		0,
 		"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
 		"4",
 		233,
 		C2_K233
 		);
 
 	/* Curve B-233 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-233",
 		"020000000000000000000000000000000000000004000000000000000001",
 		"000000000000000000000000000000000000000000000000000000000001",
 		"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
 		"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
 		"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
 		1,
 		"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
 		"2",
 		233,
 		C2_B233
 		);
 
 	/* Curve K-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"0",
 		"1",
 		"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
 		"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
 		0,
 		"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
 		"4",
 		283,
 		C2_K283
 		);
 
 	/* Curve B-283 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-283",
 		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
 		"000000000000000000000000000000000000000000000000000000000000000000000001",
 		"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
 		"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
 		"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
 		"2",
 		283,
 		C2_B283
 		);
 
 	/* Curve K-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"0",
 		"1",
 		"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
 		"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
 		1,
 		"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
 		"4",
 		409,
 		C2_K409
 		);
 
 	/* Curve B-409 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-409",
 		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
 		"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
 		"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
 		"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
 		1,
 		"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
 		"2",
 		409,
 		C2_B409
 		);
 
 	/* Curve K-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve K-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"0",
 		"1",
 		"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
 		"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
 		0,
 		"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
 		"4",
 		571,
 		C2_K571
 		);
 
 	/* Curve B-571 (FIPS PUB 186-2, App. 6) */
 	CHAR2_CURVE_TEST
 		(
 		"NIST curve B-571",
 		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
 		"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
 		"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
 		"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
 		"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
 		1,
 		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
 		"2",
 		571,
 		C2_B571
 		);
 
 	/* more tests using the last curve */
 
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
 	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
 	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
 	{
 		const EC_POINT *points[3];
 		const BIGNUM *scalars[3];
 	
 		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 		points[0] = Q;
 		points[1] = Q;
 		points[2] = Q;
 
 		if (!BN_add(y, z, BN_value_one())) ABORT;
 		if (BN_is_odd(y)) ABORT;
 		if (!BN_rshift1(y, y)) ABORT;
 		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
 		scalars[1] = y;
 
 		fprintf(stdout, "combined multiplication ...");
 		fflush(stdout);
 
 		/* z is still the group order */
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
 		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
 		if (!BN_add(z, z, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = y;
 		scalars[1] = z; /* z = -(order + y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, ".");
 		fflush(stdout);
 
 		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
 		if (!BN_add(z, x, y)) ABORT;
 		BN_set_negative(z, 1);
 		scalars[0] = x;
 		scalars[1] = y;
 		scalars[2] = z; /* z = -(x+y) */
 
 		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
 		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
 		fprintf(stdout, " ok\n\n");
 	}
 
 
 #if 0
 	timings(C2_K163, TIMING_BASE_PT, ctx);
 	timings(C2_K163, TIMING_RAND_PT, ctx);
 	timings(C2_K163, TIMING_SIMUL, ctx);
 	timings(C2_B163, TIMING_BASE_PT, ctx);
 	timings(C2_B163, TIMING_RAND_PT, ctx);
 	timings(C2_B163, TIMING_SIMUL, ctx);
 	timings(C2_K233, TIMING_BASE_PT, ctx);
 	timings(C2_K233, TIMING_RAND_PT, ctx);
 	timings(C2_K233, TIMING_SIMUL, ctx);
 	timings(C2_B233, TIMING_BASE_PT, ctx);
 	timings(C2_B233, TIMING_RAND_PT, ctx);
 	timings(C2_B233, TIMING_SIMUL, ctx);
 	timings(C2_K283, TIMING_BASE_PT, ctx);
 	timings(C2_K283, TIMING_RAND_PT, ctx);
 	timings(C2_K283, TIMING_SIMUL, ctx);
 	timings(C2_B283, TIMING_BASE_PT, ctx);
 	timings(C2_B283, TIMING_RAND_PT, ctx);
 	timings(C2_B283, TIMING_SIMUL, ctx);
 	timings(C2_K409, TIMING_BASE_PT, ctx);
 	timings(C2_K409, TIMING_RAND_PT, ctx);
 	timings(C2_K409, TIMING_SIMUL, ctx);
 	timings(C2_B409, TIMING_BASE_PT, ctx);
 	timings(C2_B409, TIMING_RAND_PT, ctx);
 	timings(C2_B409, TIMING_SIMUL, ctx);
 	timings(C2_K571, TIMING_BASE_PT, ctx);
 	timings(C2_K571, TIMING_RAND_PT, ctx);
 	timings(C2_K571, TIMING_SIMUL, ctx);
 	timings(C2_B571, TIMING_BASE_PT, ctx);
 	timings(C2_B571, TIMING_RAND_PT, ctx);
 	timings(C2_B571, TIMING_SIMUL, ctx);
 #endif
 
 
 	if (ctx)
 		BN_CTX_free(ctx);
 	BN_free(p); BN_free(a);	BN_free(b);
 	EC_GROUP_free(group);
 	EC_POINT_free(P);
 	EC_POINT_free(Q);
 	EC_POINT_free(R);
 	BN_free(x); BN_free(y); BN_free(z); BN_free(cof);
 
 	if (C2_K163) EC_GROUP_free(C2_K163);
 	if (C2_B163) EC_GROUP_free(C2_B163);
 	if (C2_K233) EC_GROUP_free(C2_K233);
 	if (C2_B233) EC_GROUP_free(C2_B233);
 	if (C2_K283) EC_GROUP_free(C2_K283);
 	if (C2_B283) EC_GROUP_free(C2_B283);
 	if (C2_K409) EC_GROUP_free(C2_K409);
 	if (C2_B409) EC_GROUP_free(C2_B409);
 	if (C2_K571) EC_GROUP_free(C2_K571);
 	if (C2_B571) EC_GROUP_free(C2_B571);
 
 	}
 
 void internal_curve_test(void)
 	{
 	EC_builtin_curve *curves = NULL;
 	size_t crv_len = 0, n = 0;
 	int    ok = 1;
 
 	crv_len = EC_get_builtin_curves(NULL, 0);
 
 	curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
 
 	if (curves == NULL)
 		return;
 
 	if (!EC_get_builtin_curves(curves, crv_len))
 		{
 		OPENSSL_free(curves);
 		return;
 		}
 
 	fprintf(stdout, "testing internal curves: ");
 		
 	for (n = 0; n < crv_len; n++)
 		{
 		EC_GROUP *group = NULL;
 		int nid = curves[n].nid;
 		if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			/* try next curve */
 			continue;
 			}
 		if (!EC_GROUP_check(group, NULL))
 			{
 			ok = 0;
 			fprintf(stdout, "\nEC_GROUP_check() failed with"
 				" curve %s\n", OBJ_nid2sn(nid));
 			EC_GROUP_free(group);
 			/* try the next curve */
 			continue;
 			}
 		fprintf(stdout, ".");
 		fflush(stdout);
 		EC_GROUP_free(group);
 		}
 	if (ok)
 		fprintf(stdout, " ok\n");
 	else
 		fprintf(stdout, " failed\n");
 	OPENSSL_free(curves);
 	return;
 	}
 
 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
 
 int main(int argc, char *argv[])
 	{	
 	
 	/* enable memory leak checking unless explicitly disabled */
 	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
 		{
 		CRYPTO_malloc_debug_init();
 		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
 		}
 	else
 		{
 		/* OPENSSL_DEBUG_MEMORY=off */
 		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
 		}
 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 	ERR_load_crypto_strings();
 
 	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
 
 	prime_field_tests();
 	puts("");
 	char2_field_tests();
 	/* test the internal curves */
 	internal_curve_test();
 
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_cleanup();
 #endif
 	CRYPTO_cleanup_all_ex_data();
 	ERR_free_strings();
 	ERR_remove_state(0);
 	CRYPTO_mem_leaks_fp(stderr);
 	
 	return 0;
 	}
 #endif
Index: releng/9.3/crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/objects/obj_dat.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/objects/obj_dat.c	(revision 284295)
@@ -1,791 +1,794 @@
 /* crypto/objects/obj_dat.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 
 /* obj_dat.h is generated from objects.h by obj_dat.pl */
 #ifndef OPENSSL_NO_OBJECT
 #include "obj_dat.h"
 #else
 /* You will have to load all the objects needed manually in the application */
 #define NUM_NID 0
 #define NUM_SN 0
 #define NUM_LN 0
 #define NUM_OBJ 0
 static unsigned char lvalues[1];
 static ASN1_OBJECT nid_objs[1];
 static ASN1_OBJECT *sn_objs[1];
 static ASN1_OBJECT *ln_objs[1];
 static ASN1_OBJECT *obj_objs[1];
 #endif
 
 static int sn_cmp(const void *a, const void *b);
 static int ln_cmp(const void *a, const void *b);
 static int obj_cmp(const void *a, const void *b);
 #define ADDED_DATA	0
 #define ADDED_SNAME	1
 #define ADDED_LNAME	2
 #define ADDED_NID	3
 
 typedef struct added_obj_st
 	{
 	int type;
 	ASN1_OBJECT *obj;
 	} ADDED_OBJ;
 
 static int new_nid=NUM_NID;
 static LHASH *added=NULL;
 
 static int sn_cmp(const void *a, const void *b)
 	{
 	const ASN1_OBJECT * const *ap = a, * const *bp = b;
 	return(strcmp((*ap)->sn,(*bp)->sn));
 	}
 
 static int ln_cmp(const void *a, const void *b)
 	{ 
 	const ASN1_OBJECT * const *ap = a, * const *bp = b;
 	return(strcmp((*ap)->ln,(*bp)->ln));
 	}
 
 /* static unsigned long add_hash(ADDED_OBJ *ca) */
 static unsigned long add_hash(const void *ca_void)
 	{
 	const ASN1_OBJECT *a;
 	int i;
 	unsigned long ret=0;
 	unsigned char *p;
 	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
 
 	a=ca->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		ret=a->length<<20L;
 		p=(unsigned char *)a->data;
 		for (i=0; ilength; i++)
 			ret^=p[i]<<((i*3)%24);
 		break;
 	case ADDED_SNAME:
 		ret=lh_strhash(a->sn);
 		break;
 	case ADDED_LNAME:
 		ret=lh_strhash(a->ln);
 		break;
 	case ADDED_NID:
 		ret=a->nid;
 		break;
 	default:
 		/* abort(); */
 		return 0;
 		}
 	ret&=0x3fffffffL;
 	ret|=ca->type<<30L;
 	return(ret);
 	}
 
 /* static int add_cmp(ADDED_OBJ *ca, ADDED_OBJ *cb) */
 static int add_cmp(const void *ca_void, const void *cb_void)
 	{
 	ASN1_OBJECT *a,*b;
 	int i;
 	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
 	const ADDED_OBJ *cb = (const ADDED_OBJ *)cb_void;
 
 	i=ca->type-cb->type;
 	if (i) return(i);
 	a=ca->obj;
 	b=cb->obj;
 	switch (ca->type)
 		{
 	case ADDED_DATA:
 		i=(a->length - b->length);
 		if (i) return(i);
 		return(memcmp(a->data,b->data,(size_t)a->length));
 	case ADDED_SNAME:
 		if (a->sn == NULL) return(-1);
 		else if (b->sn == NULL) return(1);
 		else return(strcmp(a->sn,b->sn));
 	case ADDED_LNAME:
 		if (a->ln == NULL) return(-1);
 		else if (b->ln == NULL) return(1);
 		else return(strcmp(a->ln,b->ln));
 	case ADDED_NID:
 		return(a->nid-b->nid);
 	default:
 		/* abort(); */
 		return 0;
 		}
 	}
 
 static int init_added(void)
 	{
 	if (added != NULL) return(1);
 	added=lh_new(add_hash,add_cmp);
 	return(added != NULL);
 	}
 
 static void cleanup1(ADDED_OBJ *a)
 	{
 	a->obj->nid=0;
 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
 	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	}
 
 static void cleanup2(ADDED_OBJ *a)
 	{ a->obj->nid++; }
 
 static void cleanup3(ADDED_OBJ *a)
 	{
 	if (--a->obj->nid == 0)
 		ASN1_OBJECT_free(a->obj);
 	OPENSSL_free(a);
 	}
 
 static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *)
 
 void OBJ_cleanup(void)
 	{
 	if (added == NULL) return;
 	added->down_load=0;
 	lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
 	lh_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
 	lh_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
 	lh_free(added);
 	added=NULL;
 	}
 
 int OBJ_new_nid(int num)
 	{
 	int i;
 
 	i=new_nid;
 	new_nid+=num;
 	return(i);
 	}
 
 int OBJ_add_object(const ASN1_OBJECT *obj)
 	{
 	ASN1_OBJECT *o;
 	ADDED_OBJ *ao[4]={NULL,NULL,NULL,NULL},*aop;
 	int i;
 
 	if (added == NULL)
 		if (!init_added()) return(0);
 	if ((o=OBJ_dup(obj)) == NULL) goto err;
 	if (!(ao[ADDED_NID]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if ((o->length != 0) && (obj->data != NULL))
 		if (!(ao[ADDED_DATA]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->sn != NULL)
 		if (!(ao[ADDED_SNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 	if (o->ln != NULL)
 		if (!(ao[ADDED_LNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
 
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		{
 		if (ao[i] != NULL)
 			{
 			ao[i]->type=i;
 			ao[i]->obj=o;
 			aop=(ADDED_OBJ *)lh_insert(added,ao[i]);
 			/* memory leak, buit should not normally matter */
 			if (aop != NULL)
 				OPENSSL_free(aop);
 			}
 		}
 	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA);
 
 	return(o->nid);
 err2:
 	OBJerr(OBJ_F_OBJ_ADD_OBJECT,ERR_R_MALLOC_FAILURE);
 err:
 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
 		if (ao[i] != NULL) OPENSSL_free(ao[i]);
 	if (o != NULL) OPENSSL_free(o);
 	return(NID_undef);
 	}
 
 ASN1_OBJECT *OBJ_nid2obj(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return((ASN1_OBJECT *)&(nid_objs[n]));
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2sn(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].sn);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->sn);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 const char *OBJ_nid2ln(int n)
 	{
 	ADDED_OBJ ad,*adp;
 	ASN1_OBJECT ob;
 
 	if ((n >= 0) && (n < NUM_NID))
 		{
 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		return(nid_objs[n].ln);
 		}
 	else if (added == NULL)
 		return(NULL);
 	else
 		{
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->ln);
 		else
 			{
 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
 			return(NULL);
 			}
 		}
 	}
 
 int OBJ_obj2nid(const ASN1_OBJECT *a)
 	{
 	ASN1_OBJECT **op;
 	ADDED_OBJ ad,*adp;
 
 	if (a == NULL)
 		return(NID_undef);
 	if (a->nid != 0)
 		return(a->nid);
 
+	if (a->length == 0)
+	    return NID_undef;
+
 	if (added != NULL)
 		{
 		ad.type=ADDED_DATA;
 		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((const char *)&a,(const char *)obj_objs,
 		NUM_OBJ, sizeof(ASN1_OBJECT *),obj_cmp);
 	if (op == NULL)
 		return(NID_undef);
 	return((*op)->nid);
 	}
 
 /* Convert an object name into an ASN1_OBJECT
  * if "noname" is not set then search for short and long names first.
  * This will convert the "dotted" form into an object: unlike OBJ_txt2nid
  * it can be used with any objects, not just registered ones.
  */
 
 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
 	{
 	int nid = NID_undef;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	unsigned char *p;
 	const unsigned char *cp;
 	int i, j;
 
 	if(!no_name) {
 		if( ((nid = OBJ_sn2nid(s)) != NID_undef) ||
 			((nid = OBJ_ln2nid(s)) != NID_undef) ) 
 					return OBJ_nid2obj(nid);
 	}
 
 	/* Work out size of content octets */
 	i=a2d_ASN1_OBJECT(NULL,0,s,-1);
 	if (i <= 0) {
 		/* Don't clear the error */
 		/*ERR_clear_error();*/
 		return NULL;
 	}
 	/* Work out total size */
 	j = ASN1_object_size(0,i,V_ASN1_OBJECT);
 
 	if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL;
 
 	p = buf;
 	/* Write out tag+length */
 	ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
 	/* Write out contents */
 	a2d_ASN1_OBJECT(p,i,s,-1);
 
 	cp=buf;
 	op=d2i_ASN1_OBJECT(NULL,&cp,j);
 	OPENSSL_free(buf);
 	return op;
 	}
 
 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
 {
 	int i,n=0,len,nid, first, use_bn;
 	BIGNUM *bl;
 	unsigned long l;
 	unsigned char *p;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
 	/* Ensure that, at every state, |buf| is NUL-terminated. */
 	if (buf && buf_len > 0)
 		buf[0] = '\0';
 
 	if ((a == NULL) || (a->data == NULL))
 		return(0);
 
 	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
 		{
 		const char *s;
 		s=OBJ_nid2ln(nid);
 		if (s == NULL)
 			s=OBJ_nid2sn(nid);
 		if (s)
 			{
 			if (buf)
 				BUF_strlcpy(buf,s,buf_len);
 			n=strlen(s);
 			return n;
 			}
 		}
 
 
 	len=a->length;
 	p=a->data;
 
 	first = 1;
 	bl = NULL;
 
 	while (len > 0)
 		{
 		l=0;
 		use_bn = 0;
 		for (;;)
 			{
 			unsigned char c = *p++;
 			len--;
 			if ((len == 0) && (c & 0x80))
 				goto err;
 			if (use_bn)
 				{
 				if (!BN_add_word(bl, c & 0x7f))
 					goto err;
 				}
 			else
 				l |= c  & 0x7f;
 			if (!(c & 0x80))
 				break;
 			if (!use_bn && (l > (ULONG_MAX >> 7L)))
 				{
 				if (!bl && !(bl = BN_new()))
 					goto err;
 				if (!BN_set_word(bl, l))
 					goto err;
 				use_bn = 1;
 				}
 			if (use_bn)
 				{
 				if (!BN_lshift(bl, bl, 7))
 					goto err;
 				}
 			else
 				l<<=7L;
 			}
 
 		if (first)
 			{
 			first = 0;
 			if (l >= 80)
 				{
 				i = 2;
 				if (use_bn)
 					{
 					if (!BN_sub_word(bl, 80))
 						goto err;
 					}
 				else
 					l -= 80;
 				}
 			else
 				{
 				i=(int)(l/40);
 				l-=(long)(i*40);
 				}
 			if (buf && (buf_len > 1))
 				{
 				*buf++ = i + '0';
 				*buf = '\0';
 				buf_len--;
 				}
 			n++;
 			}
 
 		if (use_bn)
 			{
 			char *bndec;
 			bndec = BN_bn2dec(bl);
 			if (!bndec)
 				goto err;
 			i = strlen(bndec);
 			if (buf)
 				{
 				if (buf_len > 1)
 					{
 					*buf++ = '.';
 					*buf = '\0';
 					buf_len--;
 					}
 				BUF_strlcpy(buf,bndec,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n++;
 			n += i;
 			OPENSSL_free(bndec);
 			}
 		else
 			{
 			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
 			i=strlen(tbuf);
 			if (buf && (buf_len > 0))
 				{
 				BUF_strlcpy(buf,tbuf,buf_len);
 				if (i > buf_len)
 					{
 					buf += buf_len;
 					buf_len = 0;
 					}
 				else
 					{
 					buf+=i;
 					buf_len-=i;
 					}
 				}
 			n+=i;
 			l=0;
 			}
 		}
 
 	if (bl)
 		BN_free(bl);
 	return n;
 
 	err:
 	if (bl)
 		BN_free(bl);
 	return -1;
 }
 
 int OBJ_txt2nid(const char *s)
 {
 	ASN1_OBJECT *obj;
 	int nid;
 	obj = OBJ_txt2obj(s, 0);
 	nid = OBJ_obj2nid(obj);
 	ASN1_OBJECT_free(obj);
 	return nid;
 }
 
 int OBJ_ln2nid(const char *s)
 	{
 	ASN1_OBJECT o,*oo= &o,**op;
 	ADDED_OBJ ad,*adp;
 
 	o.ln=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_LNAME;
 		ad.obj= &o;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs, NUM_LN,
 		sizeof(ASN1_OBJECT *),ln_cmp);
 	if (op == NULL) return(NID_undef);
 	return((*op)->nid);
 	}
 
 int OBJ_sn2nid(const char *s)
 	{
 	ASN1_OBJECT o,*oo= &o,**op;
 	ADDED_OBJ ad,*adp;
 
 	o.sn=s;
 	if (added != NULL)
 		{
 		ad.type=ADDED_SNAME;
 		ad.obj= &o;
 		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN,
 		sizeof(ASN1_OBJECT *),sn_cmp);
 	if (op == NULL) return(NID_undef);
 	return((*op)->nid);
 	}
 
 static int obj_cmp(const void *ap, const void *bp)
 	{
 	int j;
 	const ASN1_OBJECT *a= *(ASN1_OBJECT * const *)ap;
 	const ASN1_OBJECT *b= *(ASN1_OBJECT * const *)bp;
 
 	j=(a->length - b->length);
         if (j) return(j);
 	return(memcmp(a->data,b->data,a->length));
         }
 
 const char *OBJ_bsearch(const char *key, const char *base, int num, int size,
 	int (*cmp)(const void *, const void *))
 	{
 	return OBJ_bsearch_ex(key, base, num, size, cmp, 0);
 	}
 
 const char *OBJ_bsearch_ex(const char *key, const char *base, int num,
 	int size, int (*cmp)(const void *, const void *), int flags)
 	{
 	int l,h,i=0,c=0;
 	const char *p = NULL;
 
 	if (num == 0) return(NULL);
 	l=0;
 	h=num;
 	while (l < h)
 		{
 		i=(l+h)/2;
 		p= &(base[i*size]);
 		c=(*cmp)(key,p);
 		if (c < 0)
 			h=i;
 		else if (c > 0)
 			l=i+1;
 		else
 			break;
 		}
 #ifdef CHARSET_EBCDIC
 /* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and
  * I don't have perl (yet), we revert to a *LINEAR* search
  * when the object wasn't found in the binary search.
  */
 	if (c != 0)
 		{
 		for (i=0; i 0 && (*cmp)(key,&(base[(i-1)*size])) == 0)
 			i--;
 		p = &(base[i*size]);
 		}
 	return(p);
 	}
 
 int OBJ_create_objects(BIO *in)
 	{
 	MS_STATIC char buf[512];
 	int i,num=0;
 	char *o,*s,*l=NULL;
 
 	for (;;)
 		{
 		s=o=NULL;
 		i=BIO_gets(in,buf,512);
 		if (i <= 0) return(num);
 		buf[i-1]='\0';
 		if (!isalnum((unsigned char)buf[0])) return(num);
 		o=s=buf;
 		while (isdigit((unsigned char)*s) || (*s == '.'))
 			s++;
 		if (*s != '\0')
 			{
 			*(s++)='\0';
 			while (isspace((unsigned char)*s))
 				s++;
 			if (*s == '\0')
 				s=NULL;
 			else
 				{
 				l=s;
 				while ((*l != '\0') && !isspace((unsigned char)*l))
 					l++;
 				if (*l != '\0')
 					{
 					*(l++)='\0';
 					while (isspace((unsigned char)*l))
 						l++;
 					if (*l == '\0') l=NULL;
 					}
 				else
 					l=NULL;
 				}
 			}
 		else
 			s=NULL;
 		if ((o == NULL) || (*o == '\0')) return(num);
 		if (!OBJ_create(o,s,l)) return(num);
 		num++;
 		}
 	/* return(num); */
 	}
 
 int OBJ_create(const char *oid, const char *sn, const char *ln)
 	{
 	int ok=0;
 	ASN1_OBJECT *op=NULL;
 	unsigned char *buf;
 	int i;
 
 	i=a2d_ASN1_OBJECT(NULL,0,oid,-1);
 	if (i <= 0) return(0);
 
 	if ((buf=(unsigned char *)OPENSSL_malloc(i)) == NULL)
 		{
 		OBJerr(OBJ_F_OBJ_CREATE,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	i=a2d_ASN1_OBJECT(buf,i,oid,-1);
 	if (i == 0)
 		goto err;
 	op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln);
 	if (op == NULL) 
 		goto err;
 	ok=OBJ_add_object(op);
 err:
 	ASN1_OBJECT_free(op);
 	OPENSSL_free(buf);
 	return(ok);
 	}
Index: releng/9.3/crypto/openssl/crypto/pkcs7/pk7_doit.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284295)
@@ -1,1233 +1,1236 @@
 /* crypto/pkcs7/pk7_doit.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value);
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
 
 static int PKCS7_type_is_other(PKCS7* p7)
 	{
 	int isOther=1;
 	
 	int nid=OBJ_obj2nid(p7->type);
 
 	switch( nid )
 		{
 	case NID_pkcs7_data:
 	case NID_pkcs7_signed:
 	case NID_pkcs7_enveloped:
 	case NID_pkcs7_signedAndEnveloped:
 	case NID_pkcs7_digest:
 	case NID_pkcs7_encrypted:
 		isOther=0;
 		break;
 	default:
 		isOther=1;
 		}
 
 	return isOther;
 
 	}
 
 static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
 	{
 	if ( PKCS7_type_is_data(p7))
 		return p7->d.data;
 	if ( PKCS7_type_is_other(p7) && p7->d.other
 		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
 		return p7->d.other->value.octet_string;
 	return NULL;
 	}
 
 static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
 	{
 	BIO *btmp;
 	const EVP_MD *md;
 	if ((btmp=BIO_new(BIO_f_md())) == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 
 	md=EVP_get_digestbyobj(alg->algorithm);
 	if (md == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 		goto err;
 		}
 
 	BIO_set_md(btmp,md);
 	if (*pbio == NULL)
 		*pbio=btmp;
 	else if (!BIO_push(*pbio,btmp))
 		{
 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
 		goto err;
 		}
 	btmp=NULL;
 
 	return 1;
 
 	err:
 	if (btmp)
 		BIO_free(btmp);
 	return 0;
 
 	}
 
 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
 	{
 	int i;
 	BIO *out=NULL,*btmp=NULL;
 	X509_ALGOR *xa = NULL;
 	const EVP_CIPHER *evp_cipher=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	X509_ALGOR *xalg=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
 	EVP_PKEY *pkey;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 	/*
 	 * The content field in the PKCS7 ContentInfo is optional, but that really
 	 * only applies to inner content (precisely, detached signatures).
 	 *
 	 * When reading content, missing outer content is therefore treated as an
 	 * error.
 	 *
 	 * When creating content, PKCS7_content_new() must be called before
 	 * calling this method, so a NULL p7->d is always an error.
 	 */
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		md_sk=p7->d.sign->md_algs;
 		os = PKCS7_get_octet_string(p7->d.sign->contents);
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		xalg=p7->d.enveloped->enc_data->algorithm;
 		evp_cipher=p7->d.enveloped->enc_data->cipher;
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 						PKCS7_R_CIPHER_NOT_INITIALIZED);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_digest:
 		xa = p7->d.digest->md;
 		os = PKCS7_get_octet_string(p7->d.digest->contents);
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
 	for (i=0; ialgorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
 		if (ivlen > 0)
 			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
 				goto err;
 		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
 			goto err;
 		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
 			goto err;
 
 		if (ivlen > 0) {
 			if (xalg->parameter == NULL) {
 				xalg->parameter = ASN1_TYPE_new();
 				if (xalg->parameter == NULL)
 					goto err;
 			}
 			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
 			       goto err;
 		}
 
 		/* Lets do the pub key stuff :-) */
 		max=0;
 		for (i=0; icert == NULL)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
 				goto err;
 				}
 			if ((pkey=X509_get_pubkey(ri->cert)) == NULL)
 				goto err;
 			jj=EVP_PKEY_size(pkey);
 			EVP_PKEY_free(pkey);
 			if (max < jj) max=jj;
 			}
 		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		for (i=0; icert)) == NULL)
 				goto err;
 			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
 			EVP_PKEY_free(pkey);
 			if (jj <= 0)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
 				OPENSSL_free(tmp);
 				goto err;
 				}
 			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
 					ERR_R_MALLOC_FAILURE);
 				OPENSSL_free(tmp);
 				goto err;
 				}
 			}
 		OPENSSL_free(tmp);
 		OPENSSL_cleanse(key, keylen);
 
 		if (out == NULL)
 			out=btmp;
 		else
 			BIO_push(out,btmp);
 		btmp=NULL;
 		}
 
 	if (bio == NULL)
 		{
 		if (PKCS7_is_detached(p7))
 			bio=BIO_new(BIO_s_null());
 		else if (os && os->length > 0)
 			bio = BIO_new_mem_buf(os->data, os->length);
 		if(bio == NULL)
 			{
 			bio=BIO_new(BIO_s_mem());
 			if (bio == NULL)
 				goto err;
 			BIO_set_mem_eof_return(bio,0);
 			}
 		}
 	BIO_push(out,bio);
 	bio=NULL;
 	if (0)
 		{
 err:
 		if (out != NULL)
 			BIO_free_all(out);
 		if (btmp != NULL)
 			BIO_free_all(btmp);
 		out=NULL;
 		}
 	return(out);
 	}
 
 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
 	{
 	int ret;
 	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
 				pcert->cert_info->issuer);
 	if (ret)
 		return ret;
 	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
 					ri->issuer_and_serial->serial);
 	}
 
 /* int */
 BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 	{
 	int i,j;
 	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
 	unsigned char *tmp=NULL;
 	X509_ALGOR *xa;
 	ASN1_OCTET_STRING *data_body=NULL;
 	const EVP_MD *evp_md;
 	const EVP_CIPHER *evp_cipher=NULL;
 	EVP_CIPHER_CTX *evp_ctx=NULL;
 	X509_ALGOR *enc_alg=NULL;
 	STACK_OF(X509_ALGOR) *md_sk=NULL;
 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
 	PKCS7_RECIP_INFO *ri=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
 		return NULL;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
 		return NULL;
 	}
 
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signed:
 		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
 		md_sk=p7->d.sign->md_algs;
 		break;
 	case NID_pkcs7_signedAndEnveloped:
 		rsk=p7->d.signed_and_enveloped->recipientinfo;
 		md_sk=p7->d.signed_and_enveloped->md_algs;
 		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
 		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	case NID_pkcs7_enveloped:
 		rsk=p7->d.enveloped->recipientinfo;
 		enc_alg=p7->d.enveloped->enc_data->algorithm;
 		data_body=p7->d.enveloped->enc_data->enc_data;
 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
 		if (evp_cipher == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
 			goto err;
 			}
 		break;
 	default:
 		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
 	        goto err;
 		}
 
+    /* Detached content must be supplied via in_bio instead. */
+    if (data_body == NULL && in_bio == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+        goto err;
+    }
+
 	/* We will be checking the signature */
 	if (md_sk != NULL)
 		{
 		for (i=0; ialgorithm);
 			evp_md=EVP_get_digestbynid(j);
 			if (evp_md == NULL)
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
 				goto err;
 				}
 
 			BIO_set_md(btmp,evp_md);
 			if (out == NULL)
 				out=btmp;
 			else
 				BIO_push(out,btmp);
 			btmp=NULL;
 			}
 		}
 
 	if (evp_cipher != NULL)
 		{
 #if 0
 		unsigned char key[EVP_MAX_KEY_LENGTH];
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char *p;
 		int keylen,ivlen;
 		int max;
 		X509_OBJECT ret;
 #endif
 		unsigned char *tkey = NULL;
 		int tkeylen;
 		int jj;
 
 		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
 			goto err;
 			}
 
 		/* It was encrypted, we need to decrypt the secret key
 		 * with the private key */
 
 		/* Find the recipientInfo which matches the passed certificate
 		 * (if any)
 		 */
 
 		if (pcert) {
 			for (i=0; ienc_key),
 					M_ASN1_STRING_length(ri->enc_key),
 						pkey);
 				if (tret > 0)
 					{
 					memcpy(tmp, tmp2, tret);
 					OPENSSL_cleanse(tmp2, tret);
 					jj = tret;
 					}
 				ERR_clear_error();
 				}
 			OPENSSL_free(tmp2);
 			}
 		else
 			{
 			jj=EVP_PKEY_decrypt(tmp,
 				M_ASN1_STRING_data(ri->enc_key),
 				M_ASN1_STRING_length(ri->enc_key), pkey);
 			ERR_clear_error();
 			}
 
 		evp_ctx=NULL;
 		BIO_get_cipher_ctx(etmp,&evp_ctx);
 		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
 			goto err;
 		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
 			goto err;
 		/* Generate random key to counter MMA */
 		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
 		tkey = OPENSSL_malloc(tkeylen);
 		if (!tkey)
 			goto err;
 		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
 			goto err;
 		/* If we have no key use random key */
 		if (jj <= 0)
 			{
 			OPENSSL_free(tmp);
 			jj = tkeylen;
 			tmp = tkey;
 			tkey = NULL;
 			}
 
 		if (jj != tkeylen) {
 			/* Some S/MIME clients don't use the same key
 			 * and effective key length. The key length is
 			 * determined by the size of the decrypted RSA key.
 			 */
 			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
 				{
 				/* As MMA defence use random key instead */
 				OPENSSL_cleanse(tmp, jj);
 				OPENSSL_free(tmp);
 				jj = tkeylen;
 				tmp = tkey;
 				tkey = NULL;
 				}
 		} 
 		ERR_clear_error();
 		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
 			goto err;
 
 		OPENSSL_cleanse(tmp,jj);
 
 		if (tkey)
 			{
 			OPENSSL_cleanse(tkey, tkeylen);
 			OPENSSL_free(tkey);
 			}
 
 		if (out == NULL)
 			out=etmp;
 		else
 			BIO_push(out,etmp);
 		etmp=NULL;
 		}
 
 #if 1
-	if (PKCS7_is_detached(p7) || (in_bio != NULL))
-		{
-		bio=in_bio;
-		}
-	else 
-		{
+	if (in_bio != NULL) {
+		bio = in_bio;
+	} else {
 #if 0
 		bio=BIO_new(BIO_s_mem());
 		/* We need to set this so that when we have read all
 		 * the data, the encrypt BIO, if present, will read
 		 * EOF and encode the last few bytes */
 		BIO_set_mem_eof_return(bio,0);
 
 		if (data_body->length > 0)
 			BIO_write(bio,(char *)data_body->data,data_body->length);
 #else
 		if (data_body->length > 0)
 		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
 		else {
 			bio=BIO_new(BIO_s_mem());
 			BIO_set_mem_eof_return(bio,0);
 		}
 		if (bio == NULL)
 			goto err;
 #endif
 		}
 	BIO_push(out,bio);
 	bio=NULL;
 #endif
 	if (0)
 		{
 err:
 		if (out != NULL) BIO_free_all(out);
 		if (btmp != NULL) BIO_free_all(btmp);
 		if (etmp != NULL) BIO_free_all(etmp);
 		if (bio != NULL) BIO_free_all(bio);
 		out=NULL;
 		}
 	if (tmp != NULL)
 		OPENSSL_free(tmp);
 	return(out);
 	}
 
 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
 	{
 	for (;;)
 		{
 		bio=BIO_find_type(bio,BIO_TYPE_MD);
 		if (bio == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			return NULL;	
 			}
 		BIO_get_md_ctx(bio,pmd);
 		if (*pmd == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
 			return NULL;
 			}	
 		if (EVP_MD_CTX_type(*pmd) == nid)
 			return bio;
 		bio=BIO_next(bio);
 		}
 	return NULL;
 	}
 
 int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 	{
 	int ret=0;
 	int i,j;
 	BIO *btmp;
 	BUF_MEM *buf_mem=NULL;
 	BUF_MEM *buf=NULL;
 	PKCS7_SIGNER_INFO *si;
 	EVP_MD_CTX *mdc,ctx_tmp;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
 	ASN1_OCTET_STRING *os=NULL;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	EVP_MD_CTX_init(&ctx_tmp);
 	i=OBJ_obj2nid(p7->type);
 	p7->state=PKCS7_S_HEADER;
 
 	switch (i)
 		{
 	case NID_pkcs7_signedAndEnveloped:
 		/* XXXXXXXXXXXXXXXX */
 		si_sk=p7->d.signed_and_enveloped->signer_info;
 		if (!(os=M_ASN1_OCTET_STRING_new()))
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		p7->d.signed_and_enveloped->enc_data->enc_data=os;
 		break;
 	case NID_pkcs7_enveloped:
 		/* XXXXXXXXXXXXXXXX */
 		if (!(os=M_ASN1_OCTET_STRING_new()))
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		p7->d.enveloped->enc_data->enc_data=os;
 		break;
 	case NID_pkcs7_signed:
 		si_sk=p7->d.sign->signer_info;
 		os=PKCS7_get_octet_string(p7->d.sign->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.sign->contents->d.data = NULL;
 		}
 		break;
 
 	case NID_pkcs7_digest:
 		os=PKCS7_get_octet_string(p7->d.digest->contents);
 		/* If detached data then the content is excluded */
 		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
 			{
 			M_ASN1_OCTET_STRING_free(os);
 			os = NULL;
 			p7->d.digest->contents->d.data = NULL;
 			}
 		break;
 
 		}
 
 	if (si_sk != NULL)
 		{
 		if ((buf=BUF_MEM_new()) == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
 			goto err;
 			}
 		for (i=0; ipkey == NULL) continue;
 
 			j=OBJ_obj2nid(si->digest_alg->algorithm);
 
 			btmp=bio;
 
 			btmp = PKCS7_find_digest(&mdc, btmp, j);
 
 			if (btmp == NULL)
 				goto err;
 
 			/* We now have the EVP_MD_CTX, lets do the
 			 * signing. */
 			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
 			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
 				goto err;
 				}
 
 			sk=si->auth_attr;
 
 			/* If there are attributes, we add the digest
 			 * attribute and only sign the attributes */
 			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
 				{
 				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
 				unsigned int md_len, alen;
 				ASN1_OCTET_STRING *digest;
 				ASN1_UTCTIME *sign_time;
 				const EVP_MD *md_tmp;
 
 				/* Add signing time if not already present */
 				if (!PKCS7_get_signed_attribute(si,
 							NID_pkcs9_signingTime))
 					{
 					if (!(sign_time=X509_gmtime_adj(NULL,0)))
 						{
 						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 							ERR_R_MALLOC_FAILURE);
 						goto err;
 						}
 					if (!PKCS7_add_signed_attribute(si,
 						NID_pkcs9_signingTime,
 						V_ASN1_UTCTIME,sign_time))
 						{
 						M_ASN1_UTCTIME_free(sign_time);
 						goto err;
 						}
 					}
 
 				/* Add digest */
 				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
 				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
 				if (!(digest=M_ASN1_OCTET_STRING_new()))
 					{
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 						ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
 								md_len))
 					{
 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
 						ERR_R_MALLOC_FAILURE);
 					M_ASN1_OCTET_STRING_free(digest);
 					goto err;
 					}
 				if (!PKCS7_add_signed_attribute(si,
 					NID_pkcs9_messageDigest,
 					V_ASN1_OCTET_STRING,digest))
 					{
 					M_ASN1_OCTET_STRING_free(digest);
 					goto err;
 					}
 
 				/* Now sign the attributes */
 				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
 				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
 							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
 				if(!abuf) goto err;
 				EVP_SignUpdate(&ctx_tmp,abuf,alen);
 				OPENSSL_free(abuf);
 				}
 
 #ifndef OPENSSL_NO_DSA
 			if (si->pkey->type == EVP_PKEY_DSA)
 				ctx_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
  			if (si->pkey->type == EVP_PKEY_EC)
  				ctx_tmp.digest=EVP_ecdsa();
 #endif
 
 			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
 				(unsigned int *)&buf->length,si->pkey))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
 				goto err;
 				}
 			if (!ASN1_STRING_set(si->enc_digest,
 				(unsigned char *)buf->data,buf->length))
 				{
 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
 				goto err;
 				}
 			}
 		}
 	else if (i == NID_pkcs7_digest)
 		{
 		unsigned char md_data[EVP_MAX_MD_SIZE];
 		unsigned int md_len;
 		if (!PKCS7_find_digest(&mdc, bio,
 				OBJ_obj2nid(p7->d.digest->md->algorithm)))
 			goto err;
 		EVP_DigestFinal_ex(mdc,md_data,&md_len);
 		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
 		}
 
 	if (!PKCS7_is_detached(p7)) {
 		/*
 		 * NOTE(emilia): I think we only reach os == NULL here because detached
 		 * digested data support is broken.
 		 */
 		if (os == NULL)
 			goto err;
 		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
 		if (btmp == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
 			goto err;
 			}
 		BIO_get_mem_ptr(btmp,&buf_mem);
 		/* Mark the BIO read only then we can use its copy of the data
 		 * instead of making an extra copy.
 		 */
 		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
 		BIO_set_mem_eof_return(btmp, 0);
 		os->data = (unsigned char *)buf_mem->data;
 		os->length = buf_mem->length;
 #if 0
 		M_ASN1_OCTET_STRING_set(os,
 			(unsigned char *)buf_mem->data,buf_mem->length);
 #endif
 		}
 	ret=1;
 err:
 	EVP_MD_CTX_cleanup(&ctx_tmp);
 	if (buf != NULL) BUF_MEM_free(buf);
 	return(ret);
 	}
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
 	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 	{
 	PKCS7_ISSUER_AND_SERIAL *ias;
 	int ret=0,i;
 	STACK_OF(X509) *cert;
 	X509 *x509;
 
 	if (p7 == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER);
 		return 0;
 	}
 
 	if (p7->d.ptr == NULL) {
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT);
 		return 0;
 	}
 
 	if (PKCS7_type_is_signed(p7))
 		{
 		cert=p7->d.sign->cert;
 		}
 	else if (PKCS7_type_is_signedAndEnveloped(p7))
 		{
 		cert=p7->d.signed_and_enveloped->cert;
 		}
 	else
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 		}
 	/* XXXXXXXXXXXXXXXXXXXXXXX */
 	ias=si->issuer_and_serial;
 
 	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
 
 	/* were we able to find the cert in passed to us */
 	if (x509 == NULL)
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
 		goto err;
 		}
 
 	/* Lets verify */
 	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		goto err;
 		}
 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
 	i=X509_verify_cert(ctx);
 	if (i <= 0) 
 		{
 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
 		X509_STORE_CTX_cleanup(ctx);
 		goto err;
 		}
 	X509_STORE_CTX_cleanup(ctx);
 
 	return PKCS7_signatureVerify(bio, p7, si, x509);
 	err:
 	return ret;
 	}
 
 int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
 								X509 *x509)
 	{
 	ASN1_OCTET_STRING *os;
 	EVP_MD_CTX mdc_tmp,*mdc;
 	int ret=0,i;
 	int md_type;
 	STACK_OF(X509_ATTRIBUTE) *sk;
 	BIO *btmp;
 	EVP_PKEY *pkey;
 
 	EVP_MD_CTX_init(&mdc_tmp);
 
 	if (!PKCS7_type_is_signed(p7) && 
 				!PKCS7_type_is_signedAndEnveloped(p7)) {
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_WRONG_PKCS7_TYPE);
 		goto err;
 	}
 
 	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
 
 	btmp=bio;
 	for (;;)
 		{
 		if ((btmp == NULL) ||
 			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		BIO_get_md_ctx(btmp,&mdc);
 		if (mdc == NULL)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 							ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		if (EVP_MD_CTX_type(mdc) == md_type)
 			break;
 		/* Workaround for some broken clients that put the signature
 		 * OID instead of the digest OID in digest_alg->algorithm
 		 */
 		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
 			break;
 		btmp=BIO_next(btmp);
 		}
 
 	/* mdc is the digest ctx that we want, unless there are attributes,
 	 * in which case the digest is the signed attributes */
 	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
 
 	sk=si->auth_attr;
 	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
 		{
 		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
                 unsigned int md_len, alen;
 		ASN1_OCTET_STRING *message_digest;
 
 		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
 		message_digest=PKCS7_digest_from_attributes(sk);
 		if (!message_digest)
 			{
 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
 			goto err;
 			}
 		if ((message_digest->length != (int)md_len) ||
 			(memcmp(message_digest->data,md_dat,md_len)))
 			{
 #if 0
 {
 int ii;
 for (ii=0; iilength; ii++)
 	printf("%02X",message_digest->data[ii]); printf(" sent\n");
 for (ii=0; iienc_digest;
 	pkey = X509_get_pubkey(x509);
 	if (!pkey)
 		{
 		ret = -1;
 		goto err;
 		}
 #ifndef OPENSSL_NO_DSA
 	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
 #endif
 
 	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
 	EVP_PKEY_free(pkey);
 	if (i <= 0)
 		{
 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
 						PKCS7_R_SIGNATURE_FAILURE);
 		ret= -1;
 		goto err;
 		}
 	else
 		ret=1;
 err:
 	EVP_MD_CTX_cleanup(&mdc_tmp);
 	return(ret);
 	}
 
 PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
 	{
 	STACK_OF(PKCS7_RECIP_INFO) *rsk;
 	PKCS7_RECIP_INFO *ri;
 	int i;
 
 	i=OBJ_obj2nid(p7->type);
 	if (i != NID_pkcs7_signedAndEnveloped)
 		return NULL;
 	if (p7->d.signed_and_enveloped == NULL)
 		return NULL;
 	rsk=p7->d.signed_and_enveloped->recipientinfo;
 	if (rsk == NULL)
 		return NULL;
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
 	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
 	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
 	return(ri->issuer_and_serial);
 	}
 
 ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->auth_attr,nid));
 	}
 
 ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
 	{
 	return(get_attribute(si->unauth_attr,nid));
 	}
 
 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
 	{
 	int i;
 	X509_ATTRIBUTE *xa;
 	ASN1_OBJECT *o;
 
 	o=OBJ_nid2obj(nid);
 	if (!o || !sk) return(NULL);
 	for (i=0; iobject,o) == 0)
 			{
 			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
 				return(sk_ASN1_TYPE_value(xa->value.set,0));
 			else
 				return(NULL);
 			}
 		}
 	return(NULL);
 	}
 
 ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
 {
 	ASN1_TYPE *astype;
 	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
 	return astype->value.octet_string;
 }
 
 int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
 				STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->auth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
 	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->auth_attr == NULL)
 		return 0;
 	for (i=0; iauth_attr,i,
 			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
 	{
 	int i;
 
 	if (p7si->unauth_attr != NULL)
 		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
 					   X509_ATTRIBUTE_free);
 	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
 	if (p7si->unauth_attr == NULL)
 		return 0;
 	for (i=0; iunauth_attr,i,
                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
 		    == NULL)
 			return(0);
 		}
 	return(1);
 	}
 
 int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
 	}
 
 int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
 	     void *value)
 	{
 	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
 	}
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
 			 void *value)
 	{
 	X509_ATTRIBUTE *attr=NULL;
 
 	if (*sk == NULL)
 		{
 		if (!(*sk = sk_X509_ATTRIBUTE_new_null()))
 			return 0;
 new_attrib:
 		if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value)))
 			return 0;
 		if (!sk_X509_ATTRIBUTE_push(*sk,attr))
 			{
 			X509_ATTRIBUTE_free(attr);
 			return 0;
 			}
 		}
 	else
 		{
 		int i;
 
 		for (i=0; iobject) == nid)
 				{
 				X509_ATTRIBUTE_free(attr);
 				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
 				if (attr == NULL)
 					return 0;
 				if (!sk_X509_ATTRIBUTE_set(*sk,i,attr))
 					{
 					X509_ATTRIBUTE_free(attr);
 					return 0;
 					}
 				goto end;
 				}
 			}
 		goto new_attrib;
 		}
 end:
 	return(1);
 	}
 
Index: releng/9.3/crypto/openssl/crypto/x509/x509_vfy.c
===================================================================
--- releng/9.3/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284294)
+++ releng/9.3/crypto/openssl/crypto/x509/x509_vfy.c	(revision 284295)
@@ -1,1545 +1,1583 @@
 /* crypto/x509/x509_vfy.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 
 #include "cryptlib.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
 static int null_callback(int ok,X509_STORE_CTX *e);
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
 static int check_chain_extensions(X509_STORE_CTX *ctx);
 static int check_trust(X509_STORE_CTX *ctx);
 static int check_revocation(X509_STORE_CTX *ctx);
 static int check_cert(X509_STORE_CTX *ctx);
 static int check_policy(X509_STORE_CTX *ctx);
 static int internal_verify(X509_STORE_CTX *ctx);
 const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT;
 
 
 static int null_callback(int ok, X509_STORE_CTX *e)
 	{
 	return ok;
 	}
 
 #if 0
 static int x509_subject_cmp(X509 **a, X509 **b)
 	{
 	return X509_subject_name_cmp(*a,*b);
 	}
 #endif
 
 int X509_verify_cert(X509_STORE_CTX *ctx)
 	{
 	X509 *x,*xtmp,*chain_ss=NULL;
 	int bad_chain = 0;
 	X509_VERIFY_PARAM *param = ctx->param;
 	int depth,i,ok=0;
 	int num;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	STACK_OF(X509) *sktmp=NULL;
 	if (ctx->cert == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
 		return -1;
 		}
 
 	cb=ctx->verify_cb;
 
 	/* first we make sure the chain we are going to build is
 	 * present and that the first entry is in place */
 	if (ctx->chain == NULL)
 		{
 		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
 			(!sk_X509_push(ctx->chain,ctx->cert)))
 			{
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			goto end;
 			}
 		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
 		ctx->last_untrusted=1;
 		}
 
 	/* We use a temporary STACK so we can chop and hack at it */
 	if (ctx->untrusted != NULL
 	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
 		{
 		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 		goto end;
 		}
 
 	num=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,num-1);
 	depth=param->depth;
 
 
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break; /* FIXME: If this happens, we should take
 		                         * note of it and, if appropriate, use the
 		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
 		                         * code later.
 		                         */
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx, x,x)) break;
 
 		/* If we were passed a cert chain, use it first */
 		if (ctx->untrusted != NULL)
 			{
 			xtmp=find_issuer(ctx, sktmp,x);
 			if (xtmp != NULL)
 				{
 				if (!sk_X509_push(ctx->chain,xtmp))
 					{
 					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 					goto end;
 					}
 				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
 				(void)sk_X509_delete_ptr(sktmp,xtmp);
 				ctx->last_untrusted++;
 				x=xtmp;
 				num++;
 				/* reparse the full chain for
 				 * the next one */
 				continue;
 				}
 			}
 		break;
 		}
 
 	/* at this point, chain should contain a list of untrusted
 	 * certificates.  We now need to add at least one trusted one,
 	 * if possible, otherwise we complain. */
 
 	/* Examine last certificate in chain and see if it
  	 * is self signed.
  	 */
 
 	i=sk_X509_num(ctx->chain);
 	x=sk_X509_value(ctx->chain,i-1);
 	if (ctx->check_issued(ctx, x, x))
 		{
 		/* we have a self signed certificate */
 		if (sk_X509_num(ctx->chain) == 1)
 			{
 			/* We have a single self signed certificate: see if
 			 * we can find it in the store. We must have an exact
 			 * match to avoid possible impersonation.
 			 */
 			ok = ctx->get_issuer(&xtmp, ctx, x);
 			if ((ok <= 0) || X509_cmp(x, xtmp)) 
 				{
 				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
 				ctx->current_cert=x;
 				ctx->error_depth=i-1;
 				if (ok == 1) X509_free(xtmp);
 				bad_chain = 1;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			else 
 				{
 				/* We have a match: replace certificate with store version
 				 * so we get any trust settings.
 				 */
 				X509_free(x);
 				x = xtmp;
 				(void)sk_X509_set(ctx->chain, i - 1, x);
 				ctx->last_untrusted=0;
 				}
 			}
 		else
 			{
 			/* extract and save self signed certificate for later use */
 			chain_ss=sk_X509_pop(ctx->chain);
 			ctx->last_untrusted--;
 			num--;
 			x=sk_X509_value(ctx->chain,num-1);
 			}
 		}
 
 	/* We now lookup certs from the certificate store */
 	for (;;)
 		{
 		/* If we have enough, we break */
 		if (depth < num) break;
 
 		/* If we are self signed, we break */
 		if (ctx->check_issued(ctx,x,x)) break;
 
 		ok = ctx->get_issuer(&xtmp, ctx, x);
 
 		if (ok < 0) return ok;
 		if (ok == 0) break;
 
 		x = xtmp;
 		if (!sk_X509_push(ctx->chain,x))
 			{
 			X509_free(xtmp);
 			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
 			return 0;
 			}
 		num++;
 		}
 
 	/* we now have our chain, lets check it... */
 
 	/* Is last certificate looked up self signed? */
 	if (!ctx->check_issued(ctx,x,x))
 		{
 		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
 			{
 			if (ctx->last_untrusted >= num)
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
 			else
 				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
 			ctx->current_cert=x;
 			}
 		else
 			{
 
 			sk_X509_push(ctx->chain,chain_ss);
 			num++;
 			ctx->last_untrusted=num;
 			ctx->current_cert=chain_ss;
 			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
 			chain_ss=NULL;
 			}
 
 		ctx->error_depth=num-1;
 		bad_chain = 1;
 		ok=cb(0,ctx);
 		if (!ok) goto end;
 		}
 
 	/* We have the chain complete: now we need to check its purpose */
 	ok = check_chain_extensions(ctx);
 
 	if (!ok) goto end;
 
 	/* The chain extensions are OK: check trust */
 
 	if (param->trust > 0) ok = check_trust(ctx);
 
 	if (!ok) goto end;
 
 	/* We may as well copy down any DSA parameters that are required */
 	X509_get_pubkey_parameters(NULL,ctx->chain);
 
 	/* Check revocation status: we do this after copying parameters
 	 * because they may be needed for CRL signature verification.
 	 */
 
 	ok = ctx->check_revocation(ctx);
 	if(!ok) goto end;
 
 	/* At this point, we have a chain and need to verify it */
 	if (ctx->verify != NULL)
 		ok=ctx->verify(ctx);
 	else
 		ok=internal_verify(ctx);
 	if(!ok) goto end;
 
 #ifndef OPENSSL_NO_RFC3779
 	/* RFC 3779 path validation, now that CRL check has been done */
 	ok = v3_asid_validate_path(ctx);
 	if (!ok) goto end;
 	ok = v3_addr_validate_path(ctx);
 	if (!ok) goto end;
 #endif
 
 	/* If we get this far evaluate policies */
 	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
 		ok = ctx->check_policy(ctx);
 	if(!ok) goto end;
 	if (0)
 		{
 end:
 		X509_get_pubkey_parameters(NULL,ctx->chain);
 		}
 	if (sktmp != NULL) sk_X509_free(sktmp);
 	if (chain_ss != NULL) X509_free(chain_ss);
 	return ok;
 	}
 
 
 /* Given a STACK_OF(X509) find the issuer of cert (if any)
  */
 
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
 {
 	int i;
 	X509 *issuer;
 	for (i = 0; i < sk_X509_num(sk); i++)
 		{
 		issuer = sk_X509_value(sk, i);
 		if (ctx->check_issued(ctx, x, issuer))
 			return issuer;
 		}
 	return NULL;
 }
 
 /* Given a possible certificate and issuer check them */
 
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
 {
 	int ret;
 	ret = X509_check_issued(issuer, x);
 	if (ret == X509_V_OK)
 		return 1;
 	/* If we haven't asked for issuer errors don't set ctx */
 	if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
 		return 0;
 
 	ctx->error = ret;
 	ctx->current_cert = x;
 	ctx->current_issuer = issuer;
 	return ctx->verify_cb(0, ctx);
 	return 0;
 }
 
 /* Alternative lookup method: look from a STACK stored in other_ctx */
 
 static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 {
 	*issuer = find_issuer(ctx, ctx->other_ctx, x);
 	if (*issuer)
 		{
 		CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
 		return 1;
 		}
 	else
 		return 0;
 }
 	
 
 /* Check a certificate chains extensions for consistency
  * with the supplied purpose
  */
 
 static int check_chain_extensions(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok=0, must_be_ca, plen = 0;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	int proxy_path_length = 0;
 	int allow_proxy_certs =
 		!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
 	cb=ctx->verify_cb;
 
 	/* must_be_ca can have 1 of 3 values:
 	   -1: we accept both CA and non-CA certificates, to allow direct
 	       use of self-signed certificates (which are marked as CA).
 	   0:  we only accept non-CA certificates.  This is currently not
 	       used, but the possibility is present for future extensions.
 	   1:  we only accept CA certificates.  This is currently used for
 	       all certificates in the chain except the leaf certificate.
 	*/
 	must_be_ca = -1;
 
 	/* A hack to keep people who don't want to modify their software
 	   happy */
 	if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
 		allow_proxy_certs = 1;
 
 	/* Check all untrusted certificates */
 	for (i = 0; i < ctx->last_untrusted; i++)
 		{
 		int ret;
 		x = sk_X509_value(ctx->chain, i);
 		if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 			&& (x->ex_flags & EXFLAG_CRITICAL))
 			{
 			ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
 			{
 			ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		ret = X509_check_ca(x);
 		switch(must_be_ca)
 			{
 		case -1:
 			if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 				&& (ret != 1) && (ret != 0))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 		case 0:
 			if (ret != 0)
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_NON_CA;
 				}
 			else
 				ret = 1;
 			break;
 		default:
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ret = 0;
 				ctx->error = X509_V_ERR_INVALID_CA;
 				}
 			else
 				ret = 1;
 			break;
 			}
 		if (ret == 0)
 			{
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		if (ctx->param->purpose > 0)
 			{
 			ret = X509_check_purpose(x, ctx->param->purpose,
 				must_be_ca > 0);
 			if ((ret == 0)
 				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
 					&& (ret != 1)))
 				{
 				ctx->error = X509_V_ERR_INVALID_PURPOSE;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			}
 		/* Check pathlen if not self issued */
 		if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
 			   && (x->ex_pathlen != -1)
 			   && (plen > (x->ex_pathlen + proxy_path_length + 1)))
 			{
 			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
 			ctx->error_depth = i;
 			ctx->current_cert = x;
 			ok=cb(0,ctx);
 			if (!ok) goto end;
 			}
 		/* Increment path length if not self issued */
 		if (!(x->ex_flags & EXFLAG_SI))
 			plen++;
 		/* If this certificate is a proxy certificate, the next
 		   certificate must be another proxy certificate or a EE
 		   certificate.  If not, the next certificate must be a
 		   CA certificate.  */
 		if (x->ex_flags & EXFLAG_PROXY)
 			{
 			if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
 				{
 				ctx->error =
 					X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
 				ctx->error_depth = i;
 				ctx->current_cert = x;
 				ok=cb(0,ctx);
 				if (!ok) goto end;
 				}
 			proxy_path_length++;
 			must_be_ca = 0;
 			}
 		else
 			must_be_ca = 1;
 		}
 	ok = 1;
  end:
 	return ok;
 #endif
 }
 
 static int check_trust(X509_STORE_CTX *ctx)
 {
 #ifdef OPENSSL_NO_CHAIN_VERIFY
 	return 1;
 #else
 	int i, ok;
 	X509 *x;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 	cb=ctx->verify_cb;
 /* For now just check the last certificate in the chain */
 	i = sk_X509_num(ctx->chain) - 1;
 	x = sk_X509_value(ctx->chain, i);
 	ok = X509_check_trust(x, ctx->param->trust, 0);
 	if (ok == X509_TRUST_TRUSTED)
 		return 1;
 	ctx->error_depth = i;
 	ctx->current_cert = x;
 	if (ok == X509_TRUST_REJECTED)
 		ctx->error = X509_V_ERR_CERT_REJECTED;
 	else
 		ctx->error = X509_V_ERR_CERT_UNTRUSTED;
 	ok = cb(0, ctx);
 	return ok;
 #endif
 }
 
 static int check_revocation(X509_STORE_CTX *ctx)
 	{
 	int i, last, ok;
 	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
 		return 1;
 	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
 		last = sk_X509_num(ctx->chain) - 1;
 	else
 		last = 0;
 	for(i = 0; i <= last; i++)
 		{
 		ctx->error_depth = i;
 		ok = check_cert(ctx);
 		if (!ok) return ok;
 		}
 	return 1;
 	}
 
 static int check_cert(X509_STORE_CTX *ctx)
 	{
 	X509_CRL *crl = NULL;
 	X509 *x;
 	int ok, cnum;
 	cnum = ctx->error_depth;
 	x = sk_X509_value(ctx->chain, cnum);
 	ctx->current_cert = x;
 	/* Try to retrieve relevant CRL */
 	ok = ctx->get_crl(ctx, &crl, x);
 	/* If error looking up CRL, nothing we can do except
 	 * notify callback
 	 */
 	if(!ok)
 		{
 		ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
 		ok = ctx->verify_cb(0, ctx);
 		goto err;
 		}
 	ctx->current_crl = crl;
 	ok = ctx->check_crl(ctx, crl);
 	if (!ok) goto err;
 	ok = ctx->cert_crl(ctx, crl, x);
 	err:
 	ctx->current_crl = NULL;
 	X509_CRL_free(crl);
 	return ok;
 
 	}
 
 /* Check CRL times against values in X509_STORE_CTX */
 
 static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
 	{
 	time_t *ptime;
 	int i;
 	ctx->current_crl = crl;
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
 		if (!notify || !ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
 		if (!notify || !ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if(X509_CRL_get_nextUpdate(crl))
 		{
 		i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
 
 		if (i == 0)
 			{
 			ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
 			if (!notify || !ctx->verify_cb(0, ctx))
 				return 0;
 			}
 
 		if (i < 0)
 			{
 			ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
 			if (!notify || !ctx->verify_cb(0, ctx))
 				return 0;
 			}
 		}
 
 	ctx->current_crl = NULL;
 
 	return 1;
 	}
 
 /* Lookup CRLs from the supplied list. Look for matching isser name
  * and validity. If we can't find a valid CRL return the last one
  * with matching name. This gives more meaningful error codes. Otherwise
  * we'd get a CRL not found error if a CRL existed with matching name but
  * was invalid.
  */
 
 static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl,
 			X509_NAME *nm, STACK_OF(X509_CRL) *crls)
 	{
 	int i;
 	X509_CRL *crl, *best_crl = NULL;
 	for (i = 0; i < sk_X509_CRL_num(crls); i++)
 		{
 		crl = sk_X509_CRL_value(crls, i);
 		if (X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
 			continue;
 		if (check_crl_time(ctx, crl, 0))
 			{
 			*pcrl = crl;
 			CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509);
 			return 1;
 			}
 		best_crl = crl;
 		}
 	if (best_crl)
 		{
 		*pcrl = best_crl;
 		CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509);
 		}
 		
 	return 0;
 	}
 
 /* Retrieve CRL corresponding to certificate: currently just a
  * subject lookup: maybe use AKID later...
  */
 static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x)
 	{
 	int ok;
 	X509_CRL *crl = NULL;
 	X509_OBJECT xobj;
 	X509_NAME *nm;
 	nm = X509_get_issuer_name(x);
 	ok = get_crl_sk(ctx, &crl, nm, ctx->crls);
 	if (ok)
 		{
 		*pcrl = crl;
 		return 1;
 		}
 
 	ok = X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj);
 
 	if (!ok)
 		{
 		/* If we got a near match from get_crl_sk use that */
 		if (crl)
 			{
 			*pcrl = crl;
 			return 1;
 			}
 		return 0;
 		}
 
 	*pcrl = xobj.data.crl;
 	if (crl)
 		X509_CRL_free(crl);
 	return 1;
 	}
 
 /* Check CRL validity */
 static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
 	{
 	X509 *issuer = NULL;
 	EVP_PKEY *ikey = NULL;
 	int ok = 0, chnum, cnum;
 	cnum = ctx->error_depth;
 	chnum = sk_X509_num(ctx->chain) - 1;
 	/* Find CRL issuer: if not last certificate then issuer
 	 * is next certificate in chain.
 	 */
 	if(cnum < chnum)
 		issuer = sk_X509_value(ctx->chain, cnum + 1);
 	else
 		{
 		issuer = sk_X509_value(ctx->chain, chnum);
 		/* If not self signed, can't check signature */
 		if(!ctx->check_issued(ctx, issuer, issuer))
 			{
 			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) goto err;
 			}
 		}
 
 	if(issuer)
 		{
 		/* Check for cRLSign bit if keyUsage present */
 		if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
 			!(issuer->ex_kusage & KU_CRL_SIGN))
 			{
 			ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) goto err;
 			}
 
 		/* Attempt to get issuer certificate public key */
 		ikey = X509_get_pubkey(issuer);
 
 		if(!ikey)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 			ok = ctx->verify_cb(0, ctx);
 			if (!ok) goto err;
 			}
 		else
 			{
 			/* Verify CRL signature */
 			if(X509_CRL_verify(crl, ikey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
 				ok = ctx->verify_cb(0, ctx);
 				if (!ok) goto err;
 				}
 			}
 		}
 
 	ok = check_crl_time(ctx, crl, 1);
 	if (!ok)
 		goto err;
 
 	ok = 1;
 
 	err:
 	EVP_PKEY_free(ikey);
 	return ok;
 	}
 
 /* Check certificate against CRL */
 static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 	{
 	int idx, ok;
 	X509_REVOKED rtmp;
 	STACK_OF(X509_EXTENSION) *exts;
 	X509_EXTENSION *ext;
 	/* Look for serial number of certificate in CRL */
 	rtmp.serialNumber = X509_get_serialNumber(x);
 	/* Sort revoked into serial number order if not already sorted.
 	 * Do this under a lock to avoid race condition.
  	 */
 	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
 		{
 		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
 		sk_X509_REVOKED_sort(crl->crl->revoked);
 		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
 		}
 	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
 	/* If found assume revoked: want something cleverer than
 	 * this to handle entry extensions in V2 CRLs.
 	 */
 	if(idx >= 0)
 		{
 		ctx->error = X509_V_ERR_CERT_REVOKED;
 		ok = ctx->verify_cb(0, ctx);
 		if (!ok) return 0;
 		}
 
 	if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
 		return 1;
 
 	/* See if we have any critical CRL extensions: since we
 	 * currently don't handle any CRL extensions the CRL must be
 	 * rejected. 
 	 * This code accesses the X509_CRL structure directly: applications
 	 * shouldn't do this.
 	 */
 
 	exts = crl->crl->extensions;
 
 	for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
 		{
 		ext = sk_X509_EXTENSION_value(exts, idx);
 		if (ext->critical > 0)
 			{
 			ctx->error =
 				X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
 			ok = ctx->verify_cb(0, ctx);
 			if(!ok) return 0;
 			break;
 			}
 		}
 	return 1;
 	}
 
 static int check_policy(X509_STORE_CTX *ctx)
 	{
 	int ret;
 	ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
 				ctx->param->policies, ctx->param->flags);
 	if (ret == 0)
 		{
 		X509err(X509_F_CHECK_POLICY,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	/* Invalid or inconsistent extensions */
 	if (ret == -1)
 		{
 		/* Locate certificates with bad extensions and notify
 		 * callback.
 		 */
 		X509 *x;
 		int i;
 		for (i = 1; i < sk_X509_num(ctx->chain); i++)
 			{
 			x = sk_X509_value(ctx->chain, i);
 			if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
 				continue;
 			ctx->current_cert = x;
 			ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
 			ret = ctx->verify_cb(0, ctx);
 			}
 		return 1;
 		}
 	if (ret == -2)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
 		return ctx->verify_cb(0, ctx);
 		}
 
 	if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
 		{
 		ctx->current_cert = NULL;
 		ctx->error = X509_V_OK;
 		if (!ctx->verify_cb(2, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
 	{
 	time_t *ptime;
 	int i;
 
 	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
 		ptime = &ctx->param->check_time;
 	else
 		ptime = NULL;
 
 	i=X509_cmp_time(X509_get_notBefore(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i > 0)
 		{
 		ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	i=X509_cmp_time(X509_get_notAfter(x), ptime);
 	if (i == 0)
 		{
 		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	if (i < 0)
 		{
 		ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
 		ctx->current_cert=x;
 		if (!ctx->verify_cb(0, ctx))
 			return 0;
 		}
 
 	return 1;
 	}
 
 static int internal_verify(X509_STORE_CTX *ctx)
 	{
 	int ok=0,n;
 	X509 *xs,*xi;
 	EVP_PKEY *pkey=NULL;
 	int (*cb)(int xok,X509_STORE_CTX *xctx);
 
 	cb=ctx->verify_cb;
 
 	n=sk_X509_num(ctx->chain);
 	ctx->error_depth=n-1;
 	n--;
 	xi=sk_X509_value(ctx->chain,n);
 
 	if (ctx->check_issued(ctx, xi, xi))
 		xs=xi;
 	else
 		{
 		if (n <= 0)
 			{
 			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
 			ctx->current_cert=xi;
 			ok=cb(0,ctx);
 			goto end;
 			}
 		else
 			{
 			n--;
 			ctx->error_depth=n;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 
 /*	ctx->error=0;  not needed */
 	while (n >= 0)
 		{
 		ctx->error_depth=n;
 
 		/* Skip signature check for self signed certificates unless
 		 * explicitly asked for. It doesn't add any security and
 		 * just wastes time.
 		 */
 		if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
 			{
 			if ((pkey=X509_get_pubkey(xi)) == NULL)
 				{
 				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
 				ctx->current_cert=xi;
 				ok=(*cb)(0,ctx);
 				if (!ok) goto end;
 				}
 			else if (X509_verify(xs,pkey) <= 0)
 				{
 				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
 				ctx->current_cert=xs;
 				ok=(*cb)(0,ctx);
 				if (!ok)
 					{
 					EVP_PKEY_free(pkey);
 					goto end;
 					}
 				}
 			EVP_PKEY_free(pkey);
 			pkey=NULL;
 			}
 
 		xs->valid = 1;
 
 		ok = check_cert_time(ctx, xs);
 		if (!ok)
 			goto end;
 
 		/* The last error (if any) is still in the error value */
 		ctx->current_issuer=xi;
 		ctx->current_cert=xs;
 		ok=(*cb)(1,ctx);
 		if (!ok) goto end;
 
 		n--;
 		if (n >= 0)
 			{
 			xi=xs;
 			xs=sk_X509_value(ctx->chain,n);
 			}
 		}
 	ok=1;
 end:
 	return ok;
 	}
 
 int X509_cmp_current_time(ASN1_TIME *ctm)
 {
 	return X509_cmp_time(ctm, NULL);
 }
 
 int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
-	{
+{
 	char *str;
 	ASN1_TIME atm;
 	long offset;
-	char buff1[24],buff2[24],*p;
-	int i,j;
+    char buff1[24], buff2[24], *p;
+    int i, j, remaining;
 
-	p=buff1;
-	i=ctm->length;
-	str=(char *)ctm->data;
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		if ((i < 11) || (i > 17)) return 0;
-		memcpy(p,str,10);
-		p+=10;
-		str+=10;
+    p = buff1;
+    remaining = ctm->length;
+    str = (char *)ctm->data;
+    /*
+     * Note that the following (historical) code allows much more slack in the
+     * time format than RFC5280. In RFC5280, the representation is fixed:
+     * UTCTime: YYMMDDHHMMSSZ
+     * GeneralizedTime: YYYYMMDDHHMMSSZ
+     */
+    if (ctm->type == V_ASN1_UTCTIME) {
+        /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+        int min_length = sizeof("YYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 10);
+        p += 10;
+        str += 10;
+        remaining -= 10;
+    } else {
+        /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
+        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 12);
+        p += 12;
+        str += 12;
+        remaining -= 12;
 		}
-	else
-		{
-		if (i < 13) return 0;
-		memcpy(p,str,12);
-		p+=12;
-		str+=12;
-		}
 
-	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
-		{ *(p++)='0'; *(p++)='0'; }
-	else
-		{ 
-		*(p++)= *(str++);
-		*(p++)= *(str++);
-		/* Skip any fractional seconds... */
-		if (*str == '.')
-			{
+    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+        *(p++) = '0';
+        *(p++) = '0';
+    } else {
+        /* SS (seconds) */
+        if (remaining < 2)
+            return 0;
+        *(p++) = *(str++);
+        *(p++) = *(str++);
+        remaining -= 2;
+        /*
+         * Skip any (up to three) fractional seconds...
+         * TODO(emilia): in RFC5280, fractional seconds are forbidden.
+         * Can we just kill them altogether?
+         */
+        if (remaining && *str == '.') {
 			str++;
-			while ((*str >= '0') && (*str <= '9')) str++;
+            remaining--;
+            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+                if (*str < '0' || *str > '9')
+                    break;
 			}
-		
 		}
-	*(p++)='Z';
-	*(p++)='\0';
 
-	if (*str == 'Z')
-		offset=0;
-	else
-		{
+    }
+    *(p++) = 'Z';
+    *(p++) = '\0';
+
+    /* We now need either a terminating 'Z' or an offset. */
+    if (!remaining)
+        return 0;
+    if (*str == 'Z') {
+        if (remaining != 1)
+            return 0;
+        offset = 0;
+    } else {
+        /* (+-)HHMM */
 		if ((*str != '+') && (*str != '-'))
 			return 0;
-		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
-		offset+=(str[3]-'0')*10+(str[4]-'0');
+        /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
+        if (remaining != 5)
+            return 0;
+        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+            return 0;
+        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+        offset += (str[3] - '0') * 10 + (str[4] - '0');
 		if (*str == '-')
-			offset= -offset;
+            offset = -offset;
 		}
-	atm.type=ctm->type;
-	atm.length=sizeof(buff2);
-	atm.data=(unsigned char *)buff2;
+    atm.type = ctm->type;
+    atm.length = sizeof(buff2);
+    atm.data = (unsigned char *)buff2;
 
-	if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
 		return 0;
 
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		i=(buff1[0]-'0')*10+(buff1[1]-'0');
-		if (i < 50) i+=100; /* cf. RFC 2459 */
-		j=(buff2[0]-'0')*10+(buff2[1]-'0');
-		if (j < 50) j+=100;
+    if (ctm->type == V_ASN1_UTCTIME) {
+        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+        if (i < 50)
+            i += 100;           /* cf. RFC 2459 */
+        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+        if (j < 50)
+            j += 100;
 
-		if (i < j) return -1;
-		if (i > j) return 1;
+        if (i < j)
+            return -1;
+        if (i > j)
+            return 1;
 		}
-	i=strcmp(buff1,buff2);
+    i = strcmp(buff1, buff2);
 	if (i == 0) /* wait a second then return younger :-) */
 		return -1;
 	else
 		return i;
-	}
+}
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
 	return X509_time_adj(s, adj, NULL);
 }
 
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
 	{
 	time_t t;
 	int type = -1;
 
 	if (in_tm) t = *in_tm;
 	else time(&t);
 
 	t+=adj;
 	if (s) type = s->type;
 	if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t);
 	if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t);
 	return ASN1_TIME_set(s, t);
 	}
 
 int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
 	{
 	EVP_PKEY *ktmp=NULL,*ktmp2;
 	int i,j;
 
 	if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
 
 	for (i=0; i= 0; j--)
 		{
 		ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
 		EVP_PKEY_copy_parameters(ktmp2,ktmp);
 		EVP_PKEY_free(ktmp2);
 		}
 	
 	if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
 	EVP_PKEY_free(ktmp);
 	return 1;
 	}
 
 int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	/* This function is (usually) called only once, by
 	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
 	{
 	return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
 	}
 
 void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
 	{
 	return CRYPTO_get_ex_data(&ctx->ex_data,idx);
 	}
 
 int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
 	{
 	return ctx->error;
 	}
 
 void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
 	{
 	ctx->error=err;
 	}
 
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
 	{
 	return ctx->error_depth;
 	}
 
 X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
 	{
 	return ctx->current_cert;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
 	{
 	return ctx->chain;
 	}
 
 STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
 	{
 	int i;
 	X509 *x;
 	STACK_OF(X509) *chain;
 	if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL;
 	for (i = 0; i < sk_X509_num(chain); i++)
 		{
 		x = sk_X509_value(chain, i);
 		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
 		}
 	return chain;
 	}
 
 void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
 	{
 	ctx->cert=x;
 	}
 
 void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 	{
 	ctx->untrusted=sk;
 	}
 
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 	{
 	ctx->crls=sk;
 	}
 
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
 	}
 
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
 	{
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
 	}
 
 /* This function is used to set the X509_STORE_CTX purpose and trust
  * values. This is intended to be used when another structure has its
  * own trust and purpose values which (if set) will be inherited by
  * the ctx. If they aren't set then we will usually have a default
  * purpose in mind which should then be used to set the trust value.
  * An example of this is SSL use: an SSL structure will have its own
  * purpose and trust settings which the application can set: if they
  * aren't set then we use the default of SSL client/server.
  */
 
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
 				int purpose, int trust)
 {
 	int idx;
 	/* If purpose not set use default */
 	if (!purpose) purpose = def_purpose;
 	/* If we have a purpose then check it is valid */
 	if (purpose)
 		{
 		X509_PURPOSE *ptmp;
 		idx = X509_PURPOSE_get_by_id(purpose);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 			return 0;
 			}
 		ptmp = X509_PURPOSE_get0(idx);
 		if (ptmp->trust == X509_TRUST_DEFAULT)
 			{
 			idx = X509_PURPOSE_get_by_id(def_purpose);
 			if (idx == -1)
 				{
 				X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_PURPOSE_ID);
 				return 0;
 				}
 			ptmp = X509_PURPOSE_get0(idx);
 			}
 		/* If trust not set then get from purpose default */
 		if (!trust) trust = ptmp->trust;
 		}
 	if (trust)
 		{
 		idx = X509_TRUST_get_by_id(trust);
 		if (idx == -1)
 			{
 			X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
 						X509_R_UNKNOWN_TRUST_ID);
 			return 0;
 			}
 		}
 
 	if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
 	if (trust && !ctx->param->trust) ctx->param->trust = trust;
 	return 1;
 }
 
 X509_STORE_CTX *X509_STORE_CTX_new(void)
 {
 	X509_STORE_CTX *ctx;
 	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
 	if (!ctx)
 		{
 		X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
 		return NULL;
 		}
 	memset(ctx, 0, sizeof(X509_STORE_CTX));
 	return ctx;
 }
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
 	X509_STORE_CTX_cleanup(ctx);
 	OPENSSL_free(ctx);
 }
 
 int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
 	     STACK_OF(X509) *chain)
 	{
 	int ret = 1;
 	ctx->ctx=store;
 	ctx->current_method=0;
 	ctx->cert=x509;
 	ctx->untrusted=chain;
 	ctx->crls = NULL;
 	ctx->last_untrusted=0;
 	ctx->other_ctx=NULL;
 	ctx->valid=0;
 	ctx->chain=NULL;
 	ctx->error=0;
 	ctx->explicit_policy=0;
 	ctx->error_depth=0;
 	ctx->current_cert=NULL;
 	ctx->current_issuer=NULL;
 	ctx->tree = NULL;
 
 	ctx->param = X509_VERIFY_PARAM_new();
 
 	if (!ctx->param)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	/* Inherit callbacks and flags from X509_STORE if not set
 	 * use defaults.
 	 */
 
 
 	if (store)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
 	else
 		ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
 
 	if (store)
 		{
 		ctx->verify_cb = store->verify_cb;
 		ctx->cleanup = store->cleanup;
 		}
 	else
 		ctx->cleanup = 0;
 
 	if (ret)
 		ret = X509_VERIFY_PARAM_inherit(ctx->param,
 					X509_VERIFY_PARAM_lookup("default"));
 
 	if (ret == 0)
 		{
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 
 	if (store && store->check_issued)
 		ctx->check_issued = store->check_issued;
 	else
 		ctx->check_issued = check_issued;
 
 	if (store && store->get_issuer)
 		ctx->get_issuer = store->get_issuer;
 	else
 		ctx->get_issuer = X509_STORE_CTX_get1_issuer;
 
 	if (store && store->verify_cb)
 		ctx->verify_cb = store->verify_cb;
 	else
 		ctx->verify_cb = null_callback;
 
 	if (store && store->verify)
 		ctx->verify = store->verify;
 	else
 		ctx->verify = internal_verify;
 
 	if (store && store->check_revocation)
 		ctx->check_revocation = store->check_revocation;
 	else
 		ctx->check_revocation = check_revocation;
 
 	if (store && store->get_crl)
 		ctx->get_crl = store->get_crl;
 	else
 		ctx->get_crl = get_crl;
 
 	if (store && store->check_crl)
 		ctx->check_crl = store->check_crl;
 	else
 		ctx->check_crl = check_crl;
 
 	if (store && store->cert_crl)
 		ctx->cert_crl = store->cert_crl;
 	else
 		ctx->cert_crl = cert_crl;
 
 	ctx->check_policy = check_policy;
 
 
 	/* This memset() can't make any sense anyway, so it's removed. As
 	 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
 	 * corresponding "new" here and remove this bogus initialisation. */
 	/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
 	if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
 				&(ctx->ex_data)))
 		{
 		OPENSSL_free(ctx);
 		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
 		return 0;
 		}
 	return 1;
 	}
 
 /* Set alternative lookup method: just a STACK of trusted certificates.
  * This avoids X509_STORE nastiness where it isn't needed.
  */
 
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
 	ctx->other_ctx = sk;
 	ctx->get_issuer = get_issuer_sk;
 }
 
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
 	{
 	if (ctx->cleanup) ctx->cleanup(ctx);
 	if (ctx->param != NULL)
 		{
 		X509_VERIFY_PARAM_free(ctx->param);
 		ctx->param=NULL;
 		}
 	if (ctx->tree != NULL)
 		{
 		X509_policy_tree_free(ctx->tree);
 		ctx->tree=NULL;
 		}
 	if (ctx->chain != NULL)
 		{
 		sk_X509_pop_free(ctx->chain,X509_free);
 		ctx->chain=NULL;
 		}
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
 	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
 	}
 
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
 	{
 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
 	}
 
 void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
 	{
 	X509_VERIFY_PARAM_set_flags(ctx->param, flags);
 	}
 
 void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
 	{
 	X509_VERIFY_PARAM_set_time(ctx->param, t);
 	}
 
 void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
 				  int (*verify_cb)(int, X509_STORE_CTX *))
 	{
 	ctx->verify_cb=verify_cb;
 	}
 
 X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
 	{
 	return ctx->tree;
 	}
 
 int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
 	{
 	return ctx->explicit_policy;
 	}
 
 int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
 	{
 	const X509_VERIFY_PARAM *param;
 	param = X509_VERIFY_PARAM_lookup(name);
 	if (!param)
 		return 0;
 	return X509_VERIFY_PARAM_inherit(ctx->param, param);
 	}
 
 X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
 	{
 	return ctx->param;
 	}
 
 void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
 	{
 	if (ctx->param)
 		X509_VERIFY_PARAM_free(ctx->param);
 	ctx->param = param;
 	}
 
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)
 
 IMPLEMENT_STACK_OF(X509_NAME)
 
 IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
 IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
Index: releng/9.3/crypto/openssl/ssl/d1_lib.c
===================================================================
--- releng/9.3/crypto/openssl/ssl/d1_lib.c	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/d1_lib.c	(revision 284295)
@@ -1,518 +1,521 @@
 /* ssl/d1_lib.c */
 /* 
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  */
 /* ====================================================================
  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 #include 
 #define USE_SOCKETS
 #include 
 #include "ssl_locl.h"
 
 #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
 #include 
 #endif
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
 int dtls1_listen(SSL *s, struct sockaddr *client);
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
 	tls1_mac,
 	tls1_setup_key_block,
 	tls1_generate_master_secret,
 	tls1_change_cipher_state,
 	tls1_final_finish_mac,
 	TLS1_FINISH_MAC_LENGTH,
 	tls1_cert_verify_mac,
 	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
 	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
 	tls1_alert_code,
 	};
 
 long dtls1_default_timeout(void)
 	{
 	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec
 	 * is way too long for http, the cache would over fill */
 	return(60*60*2);
 	}
 
 IMPLEMENT_dtls1_meth_func(dtlsv1_base_method,
 			ssl_undefined_function,
 			ssl_undefined_function,
 			ssl_bad_method)
 
 int dtls1_new(SSL *s)
 	{
 	DTLS1_STATE *d1;
 
 	if (!ssl3_new(s)) return(0);
 	if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0);
 	memset(d1,0, sizeof *d1);
 
 	/* d1->handshake_epoch=0; */
 #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST)
 	d1->bitmap.length=64;
 #else
 	d1->bitmap.length=sizeof(d1->bitmap.map) * 8;
 #endif
 	pq_64bit_init(&(d1->bitmap.map));
 	pq_64bit_init(&(d1->bitmap.max_seq_num));
 	
 	d1->next_bitmap.length = d1->bitmap.length;
 	pq_64bit_init(&(d1->next_bitmap.map));
 	pq_64bit_init(&(d1->next_bitmap.max_seq_num));
 
 	d1->unprocessed_rcds.q=pqueue_new();
 	d1->processed_rcds.q=pqueue_new();
 	d1->buffered_messages = pqueue_new();
 	d1->sent_messages=pqueue_new();
 	d1->buffered_app_data.q=pqueue_new();
 
 	if ( s->server)
 		{
 		d1->cookie_len = sizeof(s->d1->cookie);
 		}
 
 	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
         || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
 		{
         if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
         if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
         if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
 		if ( d1->sent_messages) pqueue_free(d1->sent_messages);
 		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
 		OPENSSL_free(d1);
 		return (0);
 		}
 
 	s->d1=d1;
 	s->method->ssl_clear(s);
 	return(1);
 	}
 
 static void dtls1_clear_queues(SSL *s)
 	{
     pitem *item = NULL;
     hm_fragment *frag = NULL;
 	DTLS1_RECORD_DATA *rdata;
 
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         OPENSSL_free(frag->fragment);
         OPENSSL_free(frag);
         pitem_free(item);
         }
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
         frag = (hm_fragment *)item->data;
         OPENSSL_free(frag->fragment);
         OPENSSL_free(frag);
         pitem_free(item);
         }
 
 	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
 		{
 		rdata = (DTLS1_RECORD_DATA *) item->data;
 		if (rdata->rbuf.buf)
 			{
 			OPENSSL_free(rdata->rbuf.buf);
 			}
 		OPENSSL_free(item->data);
 		pitem_free(item);
 		}
 	}
 
 void dtls1_free(SSL *s)
 	{
 	ssl3_free(s);
 
 	dtls1_clear_queues(s);
 
     pqueue_free(s->d1->unprocessed_rcds.q);
     pqueue_free(s->d1->processed_rcds.q);
     pqueue_free(s->d1->buffered_messages);
 	pqueue_free(s->d1->sent_messages);
 	pqueue_free(s->d1->buffered_app_data.q);
 	
 	pq_64bit_free(&(s->d1->bitmap.map));
 	pq_64bit_free(&(s->d1->bitmap.max_seq_num));
 
 	pq_64bit_free(&(s->d1->next_bitmap.map));
 	pq_64bit_free(&(s->d1->next_bitmap.max_seq_num));
 
 	OPENSSL_free(s->d1);
 	s->d1 = NULL;
 	}
 
 void dtls1_clear(SSL *s)
 	{
     pqueue unprocessed_rcds;
     pqueue processed_rcds;
     pqueue buffered_messages;
 	pqueue sent_messages;
 	pqueue buffered_app_data;
 	unsigned int mtu;
 
 	if (s->d1)
 		{
 		unprocessed_rcds = s->d1->unprocessed_rcds.q;
 		processed_rcds = s->d1->processed_rcds.q;
 		buffered_messages = s->d1->buffered_messages;
 		sent_messages = s->d1->sent_messages;
 		buffered_app_data = s->d1->buffered_app_data.q;
 		mtu = s->d1->mtu;
 
 		dtls1_clear_queues(s);
 
 		pq_64bit_free(&(s->d1->bitmap.map));
 		pq_64bit_free(&(s->d1->bitmap.max_seq_num));
 
 		pq_64bit_free(&(s->d1->next_bitmap.map));
 		pq_64bit_free(&(s->d1->next_bitmap.max_seq_num));
 
 		memset(s->d1, 0, sizeof(*(s->d1)));
 
 		if (s->server)
 			{
 			s->d1->cookie_len = sizeof(s->d1->cookie);
 			}
 
 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
 			{
 			s->d1->mtu = mtu;
 			}
 
 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
 		s->d1->processed_rcds.q = processed_rcds;
 		s->d1->buffered_messages = buffered_messages;
 		s->d1->sent_messages = sent_messages;
 		s->d1->buffered_app_data.q = buffered_app_data;
 
 #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST)
 		s->d1->bitmap.length=64;
 #else
 		s->d1->bitmap.length=sizeof(s->d1->bitmap.map) * 8;
 #endif
 		pq_64bit_init(&(s->d1->bitmap.map));
 		pq_64bit_init(&(s->d1->bitmap.max_seq_num));
 		
 		s->d1->next_bitmap.length = s->d1->bitmap.length;
 		pq_64bit_init(&(s->d1->next_bitmap.map));
 		pq_64bit_init(&(s->d1->next_bitmap.max_seq_num));
 		}
 
 	ssl3_clear(s);
 	if (s->options & SSL_OP_CISCO_ANYCONNECT)
 		s->version=DTLS1_BAD_VER;
 	else
 		s->version=DTLS1_VERSION;
 	}
 
 long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
 	{
 	int ret=0;
 
 	switch (cmd)
 		{
 	case DTLS_CTRL_GET_TIMEOUT:
 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
 			{
 			ret = 1;
 			}
 		break;
 	case DTLS_CTRL_HANDLE_TIMEOUT:
 		ret = dtls1_handle_timeout(s);
 		break;
 	case DTLS_CTRL_LISTEN:
 		ret = dtls1_listen(s, parg);
 		break;
 	case SSL_CTRL_CHECK_PROTO_VERSION:
 		/* For library-internal use; checks that the current protocol
 		 * is the highest enabled version (according to s->ctx->method,
 		 * as version negotiation may have changed s->method). */
 #if DTLS_MAX_VERSION != DTLS1_VERSION
 #  error Code needs update for DTLS_method() support beyond DTLS1_VERSION.
 #endif
 		/* Just one protocol version is supported so far;
 		 * fail closed if the version is not as expected. */
 		return s->version == DTLS_MAX_VERSION;
 
 	default:
 		ret = ssl3_ctrl(s, cmd, larg, parg);
 		break;
 		}
 	return(ret);
 	}
 
 /*
  * As it's impossible to use stream ciphers in "datagram" mode, this
  * simple filter is designed to disengage them in DTLS. Unfortunately
  * there is no universal way to identify stream SSL_CIPHER, so we have
  * to explicitly list their SSL_* codes. Currently RC4 is the only one
  * available, but if new ones emerge, they will have to be added...
  */
 SSL_CIPHER *dtls1_get_cipher(unsigned int u)
 	{
 	SSL_CIPHER *ciph = ssl3_get_cipher(u);
 
 	if (ciph != NULL)
 		{
 		if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4)
 			return NULL;
 		}
 
 	return ciph;
 	}
 
 void dtls1_start_timer(SSL *s)
 	{
 	/* If timer is not set, initialize duration with 1 second */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		s->d1->timeout_duration = 1;
 		}
 	
 	/* Set timeout to current time */
 	get_current_time(&(s->d1->next_timeout));
 
 	/* Add duration to current time */
 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	}
 
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
 	{
 	struct timeval timenow;
 
 	/* If no timeout is set, just return NULL */
 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
 		{
 		return NULL;
 		}
 
 	/* Get current time */
 	get_current_time(&timenow);
 
 	/* If timer already expired, set remaining time to 0 */
 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
 		(s->d1->next_timeout.tv_sec == timenow.tv_sec &&
 		 s->d1->next_timeout.tv_usec <= timenow.tv_usec))
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		return timeleft;
 		}
 
 	/* Calculate time left until timer expires */
 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
 	timeleft->tv_sec -= timenow.tv_sec;
 	timeleft->tv_usec -= timenow.tv_usec;
 	if (timeleft->tv_usec < 0)
 		{
 		timeleft->tv_sec--;
 		timeleft->tv_usec += 1000000;
 		}
 
 	/* If remaining time is less than 15 ms, set it to 0
 	 * to prevent issues because of small devergences with
 	 * socket timeouts.
 	 */
 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
 		{
 		memset(timeleft, 0, sizeof(struct timeval));
 		}
 	
 
 	return timeleft;
 	}
 
 int dtls1_is_timer_expired(SSL *s)
 	{
 	struct timeval timeleft;
 
 	/* Get time left until timeout, return false if no timer running */
 	if (dtls1_get_timeout(s, &timeleft) == NULL)
 		{
 		return 0;
 		}
 
 	/* Return false if timer is not expired yet */
 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
 		{
 		return 0;
 		}
 
 	/* Timer expired, so return true */	
 	return 1;
 	}
 
 void dtls1_double_timeout(SSL *s)
 	{
 	s->d1->timeout_duration *= 2;
 	if (s->d1->timeout_duration > 60)
 		s->d1->timeout_duration = 60;
 	dtls1_start_timer(s);
 	}
 
 void dtls1_stop_timer(SSL *s)
 	{
 	/* Reset everything */
 	memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
 	s->d1->timeout_duration = 1;
 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
 	/* Clear retransmission buffer */
 	dtls1_clear_record_buffer(s);
 	}
 
 int dtls1_check_timeout_num(SSL *s)
 	{
 	s->d1->timeout.num_alerts++;
 
 	/* Reduce MTU after 2 unsuccessful retransmissions */
 	if (s->d1->timeout.num_alerts > 2)
 		{
 		s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);		
 		}
 
 	if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
 		{
 		/* fail the connection, enough alerts have been sent */
 		SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM,SSL_R_READ_TIMEOUT_EXPIRED);
 		return -1;
 		}
 
 	return 0;
 	}
 
 int dtls1_handle_timeout(SSL *s)
 	{
 	/* if no timer is expired, don't do anything */
 	if (!dtls1_is_timer_expired(s))
 		{
 		return 0;
 		}
 
 	dtls1_double_timeout(s);
 
 	if (dtls1_check_timeout_num(s) < 0)
 		return -1;
 
 	s->d1->timeout.read_timeouts++;
 	if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
 		{
 		s->d1->timeout.read_timeouts = 1;
 		}
 
 	dtls1_start_timer(s);
 	return dtls1_retransmit_buffered_messages(s);
 	}
 
 static void get_current_time(struct timeval *t)
 {
 #ifdef OPENSSL_SYS_WIN32
 	struct _timeb tb;
 	_ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #elif defined(OPENSSL_SYS_VMS)
 	struct timeb tb;
 	ftime(&tb);
 	t->tv_sec = (long)tb.time;
 	t->tv_usec = (long)tb.millitm * 1000;
 #else
 	gettimeofday(t, NULL);
 #endif
 }
 
 int dtls1_listen(SSL *s, struct sockaddr *client)
 	{
 	int ret;
 
+	/* Ensure there is no state left over from a previous invocation */
+	SSL_clear(s);
+
 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
 	s->d1->listen = 1;
 
 	ret = SSL_accept(s);
 	if (ret <= 0) return ret;
 	
 	(void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
 	return 1;
 	}
Index: releng/9.3/crypto/openssl/ssl/s3_clnt.c
===================================================================
--- releng/9.3/crypto/openssl/ssl/s3_clnt.c	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/s3_clnt.c	(revision 284295)
@@ -1,2868 +1,2900 @@
 /* ssl/s3_clnt.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifdef OPENSSL_FIPS
 #include 
 #endif
 
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 
 static SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 
 #ifndef OPENSSL_NO_ECDH
 static int curve_id2nid(int curve_id);
 int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
 #endif
 
 static SSL_METHOD *ssl3_get_client_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_client_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_client_method,
 			ssl_undefined_function,
 			ssl3_connect,
 			ssl3_get_client_method)
 
 int ssl3_connect(SSL *s)
 	{
 	BUF_MEM *buf=NULL;
 	unsigned long Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 	
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch(s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->new_session=1;
 			s->state=SSL_ST_CONNECT;
 			s->ctx->stats.sess_connect_renegotiate++;
 			/* break */
 		case SSL_ST_BEFORE:
 		case SSL_ST_CONNECT:
 		case SSL_ST_BEFORE|SSL_ST_CONNECT:
 		case SSL_ST_OK|SSL_ST_CONNECT:
 
 			s->server=0;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version & 0xff00 ) != 0x0300)
 				{
 				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
 				ret = -1;
 				goto end;
 				}
 				
 			/* s->version=SSL3_VERSION; */
 			s->type=SSL_ST_CONNECT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				buf=NULL;
 				}
 
 			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
 
 			/* setup buffing BIO */
 			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
 
 			/* don't push the buffering BIO quite yet */
 
 			ssl3_init_finished_mac(s);
 
 			s->state=SSL3_ST_CW_CLNT_HELLO_A;
 			s->ctx->stats.sess_connect++;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CLNT_HELLO_A:
 		case SSL3_ST_CW_CLNT_HELLO_B:
 
 			s->shutdown=0;
 			ret=ssl3_client_hello(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_HELLO_A;
 			s->init_num=0;
 
 			/* turn on buffering for the next lot of output */
 			if (s->bbio != s->wbio)
 				s->wbio=BIO_push(s->bbio,s->wbio);
 
 			break;
 
 		case SSL3_ST_CR_SRVR_HELLO_A:
 		case SSL3_ST_CR_SRVR_HELLO_B:
 			ret=ssl3_get_server_hello(s);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				{
 				s->state=SSL3_ST_CR_FINISHED_A;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_ticket_expected)
 					{
 					/* receive renewed session ticket */
 					s->state=SSL3_ST_CR_SESSION_TICKET_A;
 					}
 #endif
 				}
 			else
 				s->state=SSL3_ST_CR_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_CERT_A:
 		case SSL3_ST_CR_CERT_B:
 #ifndef OPENSSL_NO_TLSEXT
 			ret=ssl3_check_finished(s);
 			if (ret <= 0) goto end;
 			if (ret == 2)
 				{
 				s->hit = 1;
 				if (s->tlsext_ticket_expected)
 					s->state=SSL3_ST_CR_SESSION_TICKET_A;
 				else
 					s->state=SSL3_ST_CR_FINISHED_A;
 				s->init_num=0;
 				break;
 				}
 #endif
 			/* Check if it is anon DH/ECDH */
 			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
 				{
 				ret=ssl3_get_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_CR_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_CR_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_KEY_EXCH_A:
 		case SSL3_ST_CR_KEY_EXCH_B:
 			ret=ssl3_get_key_exchange(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_CERT_REQ_A;
 			s->init_num=0;
 
 			/* at this point we check that we have the
 			 * required stuff from the server */
 			if (!ssl3_check_cert_and_algorithm(s))
 				{
 				ret= -1;
 				goto end;
 				}
 			break;
 
 		case SSL3_ST_CR_CERT_REQ_A:
 		case SSL3_ST_CR_CERT_REQ_B:
 			ret=ssl3_get_certificate_request(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_SRVR_DONE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CR_SRVR_DONE_A:
 		case SSL3_ST_CR_SRVR_DONE_B:
 			ret=ssl3_get_server_done(s);
 			if (ret <= 0) goto end;
 			if (s->s3->tmp.cert_req)
 				s->state=SSL3_ST_CW_CERT_A;
 			else
 				s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 
 			break;
 
 		case SSL3_ST_CW_CERT_A:
 		case SSL3_ST_CW_CERT_B:
 		case SSL3_ST_CW_CERT_C:
 		case SSL3_ST_CW_CERT_D:
 			ret=ssl3_send_client_certificate(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_KEY_EXCH_A:
 		case SSL3_ST_CW_KEY_EXCH_B:
 			ret=ssl3_send_client_key_exchange(s);
 			if (ret <= 0) goto end;
 			/* EAY EAY EAY need to check for DH fix cert
 			 * sent back */
 			/* For TLS, cert_req is set to 2, so a cert chain
 			 * of nothing is sent, but no verify packet is sent */
 			/* XXX: For now, we do not support client 
 			 * authentication in ECDH cipher suites with
 			 * ECDH (rather than ECDSA) certificates.
 			 * We need to skip the certificate verify 
 			 * message when client's ECDH public key is sent 
 			 * inside the client certificate.
 			 */
 			if (s->s3->tmp.cert_req == 1)
 				{
 				s->state=SSL3_ST_CW_CERT_VRFY_A;
 				}
 			else
 				{
 				s->state=SSL3_ST_CW_CHANGE_A;
 				s->s3->change_cipher_spec=0;
 				}
 
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_CERT_VRFY_A:
 		case SSL3_ST_CW_CERT_VRFY_B:
 			ret=ssl3_send_client_verify(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_CHANGE_A;
 			s->init_num=0;
 			s->s3->change_cipher_spec=0;
 			break;
 
 		case SSL3_ST_CW_CHANGE_A:
 		case SSL3_ST_CW_CHANGE_B:
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_FINISHED_A;
 			s->init_num=0;
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 #ifdef OPENSSL_NO_COMP
 			s->session->compress_meth=0;
 #else
 			if (s->s3->tmp.new_compression == NULL)
 				s->session->compress_meth=0;
 			else
 				s->session->compress_meth=
 					s->s3->tmp.new_compression->id;
 #endif
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 		case SSL3_ST_CW_FINISHED_A:
 		case SSL3_ST_CW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
 				s->method->ssl3_enc->client_finished_label,
 				s->method->ssl3_enc->client_finished_label_len);
 			if (ret <= 0) goto end;
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			s->state=SSL3_ST_CW_FLUSH;
 
 			/* clear flags */
 			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
 			if (s->hit)
 				{
 				s->s3->tmp.next_state=SSL_ST_OK;
 				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
 					{
 					s->state=SSL_ST_OK;
 					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
 					s->s3->delay_buf_pop_ret=0;
 					}
 				}
 			else
 				{
 #ifndef OPENSSL_NO_TLSEXT
 				/* Allow NewSessionTicket if ticket expected */
 				if (s->tlsext_ticket_expected)
 					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
 				else
 #endif
 				
 				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
 				}
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_CR_SESSION_TICKET_A:
 		case SSL3_ST_CR_SESSION_TICKET_B:
 			ret=ssl3_get_new_session_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_FINISHED_A;
 			s->init_num=0;
 		break;
 
 		case SSL3_ST_CR_CERT_STATUS_A:
 		case SSL3_ST_CR_CERT_STATUS_B:
 			ret=ssl3_get_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CR_KEY_EXCH_A;
 			s->init_num=0;
 		break;
 #endif
 
 		case SSL3_ST_CR_FINISHED_A:
 		case SSL3_ST_CR_FINISHED_B:
 
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
 				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
 
 			if (s->hit)
 				s->state=SSL3_ST_CW_CHANGE_A;
 			else
 				s->state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_CW_FLUSH:
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			if (s->init_buf != NULL)
 				{
 				BUF_MEM_free(s->init_buf);
 				s->init_buf=NULL;
 				}
 
 			/* If we are not 'joining' the last two packets,
 			 * remove the buffering now */
 			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
 				ssl_free_wbio_buffer(s);
 			/* else do it later in ssl3_write */
 
 			s->init_num=0;
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
 			if (s->hit) s->ctx->stats.sess_hit++;
 
 			ret=1;
 			/* s->server=0; */
 			s->handshake_func=ssl3_connect;
 			s->ctx->stats.sess_connect_good++;
 
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 
 			goto end;
 			/* break; */
 			
 		default:
 			SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 
 		/* did we do anything */
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_CONNECT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	s->in_handshake--;
 	if (buf != NULL)
 		BUF_MEM_free(buf);
 	if (cb != NULL)
 		cb(s,SSL_CB_CONNECT_EXIT,ret);
 	return(ret);
 	}
 
 
 int ssl3_client_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i;
 	unsigned long Time,l;
 #ifndef OPENSSL_NO_COMP
 	int j;
 	SSL_COMP *comp;
 #endif
 
 	buf=(unsigned char *)s->init_buf->data;
 	if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
 		{
 		SSL_SESSION *sess = s->session;
 		if ((sess == NULL) ||
 			(sess->ssl_version != s->version) ||
 #ifdef OPENSSL_NO_TLSEXT
 			!sess->session_id_length ||
 #else
 			(!sess->session_id_length && !sess->tlsext_tick) ||
 #endif
 			(sess->not_resumable))
 			{
 			if (!ssl_get_new_session(s,0))
 				goto err;
 			}
 		/* else use the pre-loaded session */
 
 		p=s->s3->client_random;
 		Time=(unsigned long)time(NULL);			/* Time */
 		l2n(Time,p);
 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
 			goto err;
 
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 		s->client_version=s->version;
 
 		/* Random stuff */
 		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* Session ID */
 		if (s->new_session)
 			i=0;
 		else
 			i=s->session->session_id_length;
 		*(p++)=i;
 		if (i != 0)
 			{
 			if (i > (int)sizeof(s->session->session_id))
 				{
 				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			memcpy(p,s->session->session_id,i);
 			p+=i;
 			}
 		
 		/* Ciphers supported */
 		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
 		if (i == 0)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
 			goto err;
 			}
 		s2n(i,p);
 		p+=i;
 
 		/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 		*(p++)=1;
 #else
 		if (s->ctx->comp_methods == NULL)
 			j=0;
 		else
 			j=sk_SSL_COMP_num(s->ctx->comp_methods);
 		*(p++)=1+j;
 		for (i=0; ictx->comp_methods,i);
 			*(p++)=comp->id;
 			}
 #endif
 		*(p++)=0; /* Add the NULL method */
 #ifndef OPENSSL_NO_TLSEXT
 		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 #endif		
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_CLIENT_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_CW_CLNT_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_CLNT_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_server_hello(SSL *s)
 	{
 	STACK_OF(SSL_CIPHER) *sk;
 	SSL_CIPHER *c;
 	unsigned char *p,*d;
 	int i,al,ok;
 	unsigned int j;
 	long n;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp;
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_HELLO_A,
 		SSL3_ST_CR_SRVR_HELLO_B,
 		-1,
 		20000, /* ?? */
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
 		{
 		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
 			{
 			if ( s->d1->send_cookie == 0)
 				{
 				s->s3->tmp.reuse_message = 1;
 				return 1;
 				}
 			else /* already sent a cookie */
 				{
 				al=SSL_AD_UNEXPECTED_MESSAGE;
 				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 				goto f_err;
 				}
 			}
 		}
 	
 	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 
 	d=p=(unsigned char *)s->init_msg;
 
 	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
 		s->version=(s->version&0xff00)|p[1];
 		al=SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 	p+=2;
 
 	/* load the server hello data */
 	/* load the server random */
 	memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	/* get the session-id */
 	j= *(p++);
 
 	if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG);
 		goto f_err;
 		}
 
 	if (j != 0 && j == s->session->session_id_length
 	    && memcmp(p,s->session->session_id,j) == 0)
 	    {
 	    if(s->sid_ctx_length != s->session->sid_ctx_length
 	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length))
 		{
 		/* actually a client application bug */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 		goto f_err;
 		}
 	    s->s3->flags |= SSL3_FLAGS_CCS_OK;
 	    s->hit=1;
 	    }
 	else	/* a miss or crap from the other end */
 		{
 		/* If we were trying for session-id reuse, make a new
 		 * SSL_SESSION so we don't stuff up other people */
 		s->hit=0;
 		if (s->session->session_id_length > 0)
 			{
 			if (!ssl_get_new_session(s,0))
 				{
 				al=SSL_AD_INTERNAL_ERROR;
 				goto f_err;
 				}
 			}
 		s->session->session_id_length=j;
 		memcpy(s->session->session_id,p,j); /* j could be 0 */
 		}
 	p+=j;
 	c=ssl_get_cipher_by_char(s,p);
 	if (c == NULL)
 		{
 		/* unknown cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
 		goto f_err;
 		}
 	p+=ssl_put_cipher_by_char(s,NULL,NULL);
 
 	sk=ssl_get_ciphers_by_id(s);
 	i=sk_SSL_CIPHER_find(sk,c);
 	if (i < 0)
 		{
 		/* we did not say we would use this cipher */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
 		goto f_err;
 		}
 
 	/* Depending on the session caching (internal/external), the cipher
 	   and/or cipher_id values may not be set. Make sure that
 	   cipher_id is set and use it for comparison. */
 	if (s->session->cipher)
 		s->session->cipher_id = s->session->cipher->id;
 	if (s->hit && (s->session->cipher_id != c->id))
 		{
 /* Workaround is now obsolete */
 #if 0
 		if (!(s->options &
 			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
 #endif
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
 			goto f_err;
 			}
 		}
 	s->s3->tmp.new_cipher=c;
 
 	/* lets get the compression algorithm */
 	/* COMPRESSION */
 #ifdef OPENSSL_NO_COMP
 	if (*(p++) != 0)
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 #else
 	j= *(p++);
 	if (j == 0)
 		comp=NULL;
 	else
 		comp=ssl3_comp_find(s->ctx->comp_methods,j);
 	
 	if ((j != 0) && (comp == NULL))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
 		goto f_err;
 		}
 	else
 		{
 		s->s3->tmp.new_compression=comp;
 		}
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_serverhello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err; 
 			}
 		if (ssl_check_serverhello_tlsext(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
 				goto err;
 			}
 		}
 #endif
 
 
 	if (p != (d+n))
 		{
 		/* wrong packet length */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 #ifndef OPENSSL_NO_TLSEXT
 err:
 #endif
 	return(-1);
 	}
 
 int ssl3_get_server_certificate(SSL *s)
 	{
 	int al,i,ok,ret= -1;
 	unsigned long n,nc,llen,l;
 	X509 *x=NULL;
 	const unsigned char *q,*p;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 	SESS_CERT *sc;
 	EVP_PKEY *pkey=NULL;
 	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_A,
 		SSL3_ST_CR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
 		((s->s3->tmp.new_cipher->algorithms & SSL_aKRB5) && 
 		(s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&q,l);
 		if (x == NULL)
 			{
 			al=SSL_AD_BAD_CERTIFICATE;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto f_err;
 			}
 		if (q != (p+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		p=q;
 		}
 
 	i=ssl_verify_cert_chain(s,sk);
 	if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
 #ifndef OPENSSL_NO_KRB5
 	        && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
 	        != (SSL_aKRB5|SSL_kKRB5)
 #endif /* OPENSSL_NO_KRB5 */
 	        )
 		{
 		al=ssl_verify_alarm_type(s->verify_result);
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
 		goto f_err; 
 		}
 	ERR_clear_error(); /* but we keep s->verify_result */
 
 	sc=ssl_sess_cert_new();
 	if (sc == NULL) goto err;
 
 	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
 	s->session->sess_cert=sc;
 
 	sc->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does include the peer's
 	 * certificate, which we don't include in s3_srvr.c */
 	x=sk_X509_value(sk,0);
 	sk=NULL;
  	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
 
 	pkey=X509_get_pubkey(x);
 
 	/* VRS: allow null cert if auth == KRB5 */
 	need_cert =	((s->s3->tmp.new_cipher->algorithms
 	                 & (SSL_MKEY_MASK|SSL_AUTH_MASK))
 	                 == (SSL_aKRB5|SSL_kKRB5))? 0: 1;
 
 #ifdef KSSL_DEBUG
 	printf("pkey,x = %p, %p\n", (void *)pkey,(void *)x);
 	printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
 	printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name,
 	        s->s3->tmp.new_cipher->algorithms, need_cert);
 #endif    /* KSSL_DEBUG */
 
 	if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
 		goto f_err;
 		}
 
 	i=ssl_cert_type(x,pkey);
 	if (need_cert && i < 0)
 		{
 		x=NULL;
 		al=SSL3_AL_FATAL;
 		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
 			SSL_R_UNKNOWN_CERTIFICATE_TYPE);
 		goto f_err;
 		}
 
 	if (need_cert)
 		{
 		sc->peer_cert_type=i;
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		/* Why would the following ever happen?
 		 * We just created sc a couple of lines ago. */
 		if (sc->peer_pkeys[i].x509 != NULL)
 			X509_free(sc->peer_pkeys[i].x509);
 		sc->peer_pkeys[i].x509=x;
 		sc->peer_key= &(sc->peer_pkeys[i]);
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		s->session->peer=x;
 		}
 	else
 		{
 		sc->peer_cert_type=i;
 		sc->peer_key= NULL;
 
 		if (s->session->peer != NULL)
 			X509_free(s->session->peer);
 		s->session->peer=NULL;
 		}
 	s->session->verify_result = s->verify_result;
 
 	x=NULL;
 	ret=1;
 
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	EVP_PKEY_free(pkey);
 	X509_free(x);
 	sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_get_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
 #endif
 	EVP_MD_CTX md_ctx;
 	unsigned char *param,*p;
 	int al,j,ok;
 	long i,param_len,n,alg;
 	EVP_PKEY *pkey=NULL;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh = NULL;
 	BN_CTX *bn_ctx = NULL;
 	EC_POINT *srvr_ecpoint = NULL;
 	int curve_nid = 0;
 	int encoded_pt_len = 0;
 #endif
 
 	/* use same message size as in ssl3_get_certificate_request()
 	 * as ServerKeyExchange message may be skipped */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_KEY_EXCH_A,
 		SSL3_ST_CR_KEY_EXCH_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	alg=s->s3->tmp.new_cipher->algorithms;
 	EVP_MD_CTX_init(&md_ctx);
 
 	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
 		{
 		/*
 		 * Can't skip server key exchange if this is an ephemeral
 		 * ciphersuite.
 		 */
 		if (alg & (SSL_kEDH|SSL_kECDHE))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
 			al = SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	param=p=(unsigned char *)s->init_msg;
 
 	if (s->session->sess_cert != NULL)
 		{
 #ifndef OPENSSL_NO_RSA
 		if (s->session->sess_cert->peer_rsa_tmp != NULL)
 			{
 			RSA_free(s->session->sess_cert->peer_rsa_tmp);
 			s->session->sess_cert->peer_rsa_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		if (s->session->sess_cert->peer_dh_tmp)
 			{
 			DH_free(s->session->sess_cert->peer_dh_tmp);
 			s->session->sess_cert->peer_dh_tmp=NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->session->sess_cert->peer_ecdh_tmp)
 			{
 			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
 			s->session->sess_cert->peer_ecdh_tmp=NULL;
 			}
 #endif
 		}
 	else
 		{
 		s->session->sess_cert=ssl_sess_cert_new();
 		}
 
 	/* Total length of the parameters including the length prefix */
 	param_len=0;
 
 	al=SSL_AD_DECODE_ERROR;
 #ifndef OPENSSL_NO_RSA
 	if (alg & SSL_kRSA)
 		{
 		/* Temporary RSA keys only allowed in export ciphersuites */
 		if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher))
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 			goto f_err;
 			}
 		if ((rsa=RSA_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 		/* this should be because we are using an export cipher */
 		if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 		else
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		s->session->sess_cert->peer_rsa_tmp=rsa;
 		rsa=NULL;
 		}
 #else /* OPENSSL_NO_RSA */
 	if (0)
 		;
 #endif
 #ifndef OPENSSL_NO_DH
 	else if (alg & SSL_kEDH)
 		{
 		if ((dh=DH_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
 			goto err;
 			}
 
 		param_len = 2;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->p=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->g=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 
 		if (2 > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 		param_len += 2;
 
 		n2s(p,i);
 
 		if (i > n - param_len)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
 			goto f_err;
 			}
 		param_len += i;
 
 		if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
 			goto err;
 			}
 		p+=i;
 		n-=param_len;
 
 #ifndef OPENSSL_NO_RSA
 		if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #else
 		if (0)
 			;
 #endif
 #ifndef OPENSSL_NO_DSA
 		else if (alg & SSL_aDSS)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
 #endif
 		/* else anonymous DH, so no certificate or pkey. */
 
 		s->session->sess_cert->peer_dh_tmp=dh;
 		dh=NULL;
 		}
 	else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
 		{
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_DH */
 
 #ifndef OPENSSL_NO_ECDH
 	else if (alg & SSL_kECDHE)
 		{
 		EC_GROUP *ngroup;
 		const EC_GROUP *group;
 
 		if ((ecdh=EC_KEY_new()) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		/* Extract elliptic curve parameters and the
 		 * server's ephemeral ECDH public key.
 		 * Keep accumulating lengths of various components in
 		 * param_len and make sure it never exceeds n.
 		 */
 
 		/* XXX: For now we only support named (not generic) curves
 		 * and the ECParameters in this case is just three bytes. We
 		 * also need one byte for the length of the encoded point
 		 */
 		param_len=4;
 		if (param_len > n)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
 				SSL_R_LENGTH_TOO_SHORT);
 			goto f_err;
 			}
 
 		if ((*p != NAMED_CURVE_TYPE) || 
 		    ((curve_nid = curve_id2nid(*(p + 2))) == 0))
 			{
 			al=SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
 			goto f_err;
 			}
 
 		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
 		if (ngroup == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		if (EC_KEY_set_group(ecdh, ngroup) == 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB);
 			goto err;
 			}
 		EC_GROUP_free(ngroup);
 
 		group = EC_KEY_get0_group(ecdh);
 
 		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 		    (EC_GROUP_get_degree(group) > 163))
 			{
 			al=SSL_AD_EXPORT_RESTRICTION;
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 			goto f_err;
 			}
 
 		p+=3;
 
 		/* Next, get the encoded ECPoint */
 		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
 		    ((bn_ctx = BN_CTX_new()) == NULL))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		encoded_pt_len = *p;  /* length of encoded point */
 		p+=1;
 
 		if ((encoded_pt_len > n - param_len) ||
 		    (EC_POINT_oct2point(group, srvr_ecpoint, 
 			p, encoded_pt_len, bn_ctx) == 0))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
 			goto f_err;
 			}
 		param_len += encoded_pt_len;
 
 		n-=param_len;
 		p+=encoded_pt_len;
 
 		/* The ECC/TLS specification does not mention
 		 * the use of DSA to sign ECParameters in the server
 		 * key exchange message. We do support RSA and ECDSA.
 		 */
 		if (0) ;
 #ifndef OPENSSL_NO_RSA
 		else if (alg & SSL_aRSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		else if (alg & SSL_aECDSA)
 			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 #endif
 		/* else anonymous ECDH, so no certificate or pkey. */
 		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
 		s->session->sess_cert->peer_ecdh_tmp=ecdh;
 		ecdh=NULL;
 		BN_CTX_free(bn_ctx);
 		bn_ctx = NULL;
 		EC_POINT_free(srvr_ecpoint);
 		srvr_ecpoint = NULL;
 		}
 	else if (alg & SSL_kECDH)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 		goto f_err;
 		}
 #endif /* !OPENSSL_NO_ECDH */
 	if (alg & SSL_aFZA)
 		{
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
 		goto f_err;
 		}
 
 
 	/* p points to the next byte, there are 'n' bytes left */
 
 	/* if it was signed, check the signature */
 	if (pkey != NULL)
 		{
 		n2s(p,i);
 		n-=2;
 		j=EVP_PKEY_size(pkey);
 
 		/* Check signature length. If n is 0 then signature is empty */
 		if ((i != n) || (n > j) || (n <= 0))
 			{
 			/* wrong packet length */
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
 			goto f_err;
 			}
 
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA)
 			{
 			int num;
 			unsigned int size;
 
 			j=0;
 			q=md_buf;
 			for (num=2; num > 0; num--)
 				{
 				EVP_MD_CTX_set_flags(&md_ctx,
 					EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 				EVP_DigestInit_ex(&md_ctx,(num == 2)
 					?s->ctx->md5:s->ctx->sha1, NULL);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_DigestUpdate(&md_ctx,param,param_len);
 				EVP_DigestFinal_ex(&md_ctx,q,&size);
 				q+=size;
 				j+=size;
 				}
 			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
 								pkey->pkey.rsa);
 			if (i < 0)
 				{
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
 				goto f_err;
 				}
 			if (i == 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DSA
 			if (pkey->type == EVP_PKEY_DSA)
 			{
 			/* lets do DSS */
 			EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
 			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			if (pkey->type == EVP_PKEY_EC)
 			{
 			/* let's do ECDSA */
 			EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 			EVP_VerifyUpdate(&md_ctx,param,param_len);
 			if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
 				{
 				/* bad signature */
 				al=SSL_AD_DECRYPT_ERROR;
 				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
 				goto f_err;
 				}
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		}
 	else
 		{
 		/* still data left over */
 		if (!(alg & SSL_aNULL))
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		if (n != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
 			goto f_err;
 			}
 		}
 	EVP_PKEY_free(pkey);
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	EVP_PKEY_free(pkey);
 #ifndef OPENSSL_NO_RSA
 	if (rsa != NULL)
 		RSA_free(rsa);
 #endif
 #ifndef OPENSSL_NO_DH
 	if (dh != NULL)
 		DH_free(dh);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	EC_POINT_free(srvr_ecpoint);
 	if (ecdh != NULL)
 		EC_KEY_free(ecdh);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_get_certificate_request(SSL *s)
 	{
 	int ok,ret=0;
 	unsigned long n,nc,l;
 	unsigned int llen,ctype_num,i;
 	X509_NAME *xn=NULL;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509_NAME) *ca_sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_REQ_A,
 		SSL3_ST_CR_CERT_REQ_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	s->s3->tmp.cert_req=0;
 
 	if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE);
 		goto err;
 		}
 
 	/* TLS does not like anon-DH with client cert */
 	if (s->version > SSL3_VERSION)
 		{
 		l=s->s3->tmp.new_cipher->algorithms;
 		if (l & SSL_aNULL)
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
 			goto err;
 			}
 		}
 
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	/* get the certificate types */
 	ctype_num= *(p++);
 	if (ctype_num > SSL3_CT_NUMBER)
 		ctype_num=SSL3_CT_NUMBER;
 	for (i=0; is3->tmp.ctype[i]= p[i];
 	p+=ctype_num;
 
 	/* get the CA RDNs */
 	n2s(p,llen);
 #if 0
 {
 FILE *out;
 out=fopen("/tmp/vsign.der","w");
 fwrite(p,1,llen,out);
 fclose(out);
 }
 #endif
 
 	if ((llen+ctype_num+2+1) != n)
 		{
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
 		goto err;
 		}
 
 	for (nc=0; nc llen)
 			{
 			if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 				goto cont; /* netscape bugs */
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG);
 			goto err;
 			}
 
 		q=p;
 
 		if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
 			{
 			/* If netscape tolerance is on, ignore errors */
 			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
 				goto cont;
 			else
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB);
 				goto err;
 				}
 			}
 
 		if (q != (p+l))
 			{
 			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH);
 			goto err;
 			}
 		if (!sk_X509_NAME_push(ca_sk,xn))
 			{
 			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
 		p+=l;
 		nc+=l+2;
 		}
 
 	if (0)
 		{
 cont:
 		ERR_clear_error();
 		}
 
 	/* we should setup a certificate to return.... */
 	s->s3->tmp.cert_req=1;
 	s->s3->tmp.ctype_num=ctype_num;
 	if (s->s3->tmp.ca_names != NULL)
 		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
 	s->s3->tmp.ca_names=ca_sk;
 	ca_sk=NULL;
 
 	ret=1;
 err:
 	if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
 	return(ret);
 	}
 
 static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
 	{
 	return(X509_NAME_cmp(*a,*b));
 	}
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_get_new_session_ticket(SSL *s)
 	{
 	int ok,al,ret=0, ticklen;
 	long n;
 	const unsigned char *p;
 	unsigned char *d;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SESSION_TICKET_A,
 		SSL3_ST_CR_SESSION_TICKET_B,
 		-1,
 		16384,
 		&ok);
 
 	if (!ok)
 		return((int)n);
 
 	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
 		{
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
 		goto f_err;
 		}
 	if (n < 6)
 		{
 		/* need at least ticket_lifetime_hint + ticket length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 
 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
 	if (ticklen + 6 != n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->session->tlsext_tick)
 		{
 		OPENSSL_free(s->session->tlsext_tick);
 		s->session->tlsext_ticklen = 0;
 		}
 	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
 	if (!s->session->tlsext_tick)
 		{
 		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 	memcpy(s->session->tlsext_tick, p, ticklen);
 	s->session->tlsext_ticklen = ticklen;
 	/* There are two ways to detect a resumed ticket sesion.
 	 * One is to set an appropriate session ID and then the server
 	 * must return a match in ServerHello. This allows the normal
 	 * client session ID matching to work and we know much 
 	 * earlier that the ticket has been accepted.
 	 * 
 	 * The other way is to set zero length session ID when the
 	 * ticket is presented and rely on the handshake to determine
 	 * session resumption.
 	 *
 	 * We choose the former approach because this fits in with
 	 * assumptions elsewhere in OpenSSL. The session ID is set
 	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
 	 * ticket.
 	 */ 
 	EVP_Digest(p, ticklen,
 			s->session->session_id, &s->session->session_id_length,
 #ifndef OPENSSL_NO_SHA256
 							EVP_sha256(), NULL);
 #else
 							EVP_sha1(), NULL);
 #endif
 	ret=1;
 	return(ret);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 	return(-1);
 	}
 
 int ssl3_get_cert_status(SSL *s)
 	{
 	int ok, al;
 	unsigned long resplen;
 	long n;
 	const unsigned char *p;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_STATUS_A,
 		SSL3_ST_CR_CERT_STATUS_B,
 		SSL3_MT_CERTIFICATE_STATUS,
 		16384,
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n < 4)
 		{
 		/* need at least status type + length */
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	p = (unsigned char *)s->init_msg;
 	if (*p++ != TLSEXT_STATUSTYPE_ocsp)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
 		goto f_err;
 		}
 	n2l3(p, resplen);
 	if (resplen + 4 != (unsigned long)n)
 		{
 		al = SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if (s->tlsext_ocsp_resp)
 		OPENSSL_free(s->tlsext_ocsp_resp);
 	s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
 	if (!s->tlsext_ocsp_resp)
 		{
 		al = SSL_AD_INTERNAL_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 		goto f_err;
 		}
 	s->tlsext_ocsp_resplen = resplen;
 	if (s->ctx->tlsext_status_cb)
 		{
 		int ret;
 		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 		if (ret == 0)
 			{
 			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
 			goto f_err;
 			}
 		if (ret < 0)
 			{
 			al = SSL_AD_INTERNAL_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
 			goto f_err;
 			}
 		}
 	return 1;
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 	return(-1);
 	}
 #endif
 
 int ssl3_get_server_done(SSL *s)
 	{
 	int ok,ret=0;
 	long n;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_SRVR_DONE_A,
 		SSL3_ST_CR_SRVR_DONE_B,
 		SSL3_MT_SERVER_DONE,
 		30, /* should be very small, like 0 :-) */
 		&ok);
 
 	if (!ok) return((int)n);
 	if (n > 0)
 		{
 		/* should contain no data */
 		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH);
 		return -1;
 		}
 	ret=1;
 	return(ret);
 	}
 
 
 int ssl3_send_client_key_exchange(SSL *s)
 	{
 	unsigned char *p,*d;
 	int n;
 	unsigned long l;
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_KRB5
 	KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *clnt_ecdh = NULL;
 	const EC_POINT *srvr_ecpoint = NULL;
 	EVP_PKEY *srvr_pub_pkey = NULL;
 	unsigned char *encodedPoint = NULL;
 	int encoded_pt_len = 0;
 	BN_CTX * bn_ctx = NULL;
 #endif
 
 	if (s->state == SSL3_ST_CW_KEY_EXCH_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		l=s->s3->tmp.new_cipher->algorithms;
 
 		/* Fool emacs indentation */
 		if (0) {}
 #ifndef OPENSSL_NO_RSA
 		else if (l & SSL_kRSA)
 			{
 			RSA *rsa;
 			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 
 			if (s->session->sess_cert == NULL)
 				{
 				/* We should always have a server certificate with SSL_kRSA. */
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if (s->session->sess_cert->peer_rsa_tmp != NULL)
 				rsa=s->session->sess_cert->peer_rsa_tmp;
 			else
 				{
 				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
 				if ((pkey == NULL) ||
 					(pkey->type != EVP_PKEY_RSA) ||
 					(pkey->pkey.rsa == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 				rsa=pkey->pkey.rsa;
 				EVP_PKEY_free(pkey);
 				}
 				
 			tmp_buf[0]=s->client_version>>8;
 			tmp_buf[1]=s->client_version&0xff;
 			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 					goto err;
 
 			s->session->master_key_length=sizeof tmp_buf;
 
 			q=p;
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				p+=2;
 			n=RSA_public_encrypt(sizeof tmp_buf,
 				tmp_buf,p,rsa,RSA_PKCS1_PADDING);
 #ifdef PKCS1_CHECK
 			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
 			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
 #endif
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
 				goto err;
 				}
 
 			/* Fix buf for TLS and beyond */
 			if (s->version > SSL3_VERSION)
 				{
 				s2n(n,q);
 				n+=2;
 				}
 
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf,sizeof tmp_buf);
 			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
 			}
 #endif
 #ifndef OPENSSL_NO_KRB5
 		else if (l & SSL_kKRB5)
 			{
 			krb5_error_code	krb5rc;
 			KSSL_CTX	*kssl_ctx = s->kssl_ctx;
 			/*  krb5_data	krb5_ap_req;  */
 			krb5_data	*enc_ticket;
 			krb5_data	authenticator, *authp = NULL;
 			EVP_CIPHER_CTX	ciph_ctx;
 			EVP_CIPHER	*enc = NULL;
 			unsigned char	iv[EVP_MAX_IV_LENGTH];
 			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH 
 						+ EVP_MAX_IV_LENGTH];
 			int 		padl, outl = sizeof(epms);
 
 			EVP_CIPHER_CTX_init(&ciph_ctx);
 
 #ifdef KSSL_DEBUG
 			printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
 			        l, SSL_kKRB5);
 #endif	/* KSSL_DEBUG */
 
 			authp = NULL;
 #ifdef KRB5SENDAUTH
 			if (KRB5SENDAUTH)  authp = &authenticator;
 #endif	/* KRB5SENDAUTH */
 
 			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp,
 				&kssl_err);
 			enc = kssl_map_enc(kssl_ctx->enctype);
 			if (enc == NULL)
 			    goto err;
 #ifdef KSSL_DEBUG
 			{
 			printf("kssl_cget_tkt rtn %d\n", krb5rc);
 			if (krb5rc && kssl_err.text)
 			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text);
 			}
 #endif	/* KSSL_DEBUG */
 
 			if (krb5rc)
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,
 						SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 						kssl_err.reason);
 				goto err;
 				}
 
 			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ
 			**  in place of RFC 2712 KerberosWrapper, as in:
 			**
 			**  Send ticket (copy to *p, set n = length)
 			**  n = krb5_ap_req.length;
 			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length);
 			**  if (krb5_ap_req.data)  
 			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req);
 			**
 			**  Now using real RFC 2712 KerberosWrapper
 			**  (Thanks to Simon Wilkinson )
 			**  Note: 2712 "opaque" types are here replaced
 			**  with a 2-byte length followed by the value.
 			**  Example:
 			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms
 			**  Where "xx xx" = length bytes.  Shown here with
 			**  optional authenticator omitted.
 			*/
 
 			/*  KerberosWrapper.Ticket		*/
 			s2n(enc_ticket->length,p);
 			memcpy(p, enc_ticket->data, enc_ticket->length);
 			p+= enc_ticket->length;
 			n = enc_ticket->length + 2;
 
 			/*  KerberosWrapper.Authenticator	*/
 			if (authp  &&  authp->length)  
 				{
 				s2n(authp->length,p);
 				memcpy(p, authp->data, authp->length);
 				p+= authp->length;
 				n+= authp->length + 2;
 				
 				free(authp->data);
 				authp->data = NULL;
 				authp->length = 0;
 				}
 			else
 				{
 				s2n(0,p);/*  null authenticator length	*/
 				n+=2;
 				}
  
 			    tmp_buf[0]=s->client_version>>8;
 			    tmp_buf[1]=s->client_version&0xff;
 			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
 				goto err;
 
 			/*  20010420 VRS.  Tried it this way; failed.
 			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL);
 			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx,
 			**				kssl_ctx->length);
 			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv);
 			*/
 
 			memset(iv, 0, sizeof iv);  /* per RFC 1510 */
 			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,
 				kssl_ctx->key,iv);
 			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf,
 				sizeof tmp_buf);
 			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
 			outl += padl;
 			if (outl > sizeof epms)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 			EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
 			/*  KerberosWrapper.EncryptedPreMasterSecret	*/
 			s2n(outl,p);
 			memcpy(p, epms, outl);
 			p+=outl;
 			n+=outl + 2;
 
 			s->session->master_key_length=
 			        s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,
 					tmp_buf, sizeof tmp_buf);
 
 			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf);
 			OPENSSL_cleanse(epms, outl);
 			}
 #endif
 #ifndef OPENSSL_NO_DH
 		else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 			{
 			DH *dh_srvr,*dh_clnt;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 			        }
 
 			if (s->session->sess_cert->peer_dh_tmp != NULL)
 				dh_srvr=s->session->sess_cert->peer_dh_tmp;
 			else
 				{
 				/* we get them from the cert */
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
 				goto err;
 				}
 			
 			/* generate a new random key */
 			if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 			if (!DH_generate_key(dh_clnt))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			/* use the 'p' output buffer for the DH key, but
 			 * make sure to clear it out afterwards */
 
 			n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
 
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length=
 				s->method->ssl3_enc->generate_master_secret(s,
 					s->session->master_key,p,n);
 			/* clean up */
 			memset(p,0,n);
 
 			/* send off the data */
 			n=BN_num_bytes(dh_clnt->pub_key);
 			s2n(n,p);
 			BN_bn2bin(dh_clnt->pub_key,p);
 			n+=2;
 
 			DH_free(dh_clnt);
 
 			/* perhaps clean things up a bit EAY EAY EAY EAY*/
 			}
 #endif
 
 #ifndef OPENSSL_NO_ECDH 
 		else if ((l & SSL_kECDH) || (l & SSL_kECDHE))
 			{
 			const EC_GROUP *srvr_group = NULL;
 			EC_KEY *tkey;
 			int ecdh_clnt_cert = 0;
 			int field_size = 0;
 
 			if (s->session->sess_cert == NULL) 
 				{
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 				goto err;
 				}
 
 			/* Did we send out the client's
 			 * ECDH share for use in premaster
 			 * computation as part of client certificate?
 			 * If so, set ecdh_clnt_cert to 1.
 			 */
 			if ((l & SSL_kECDH) && (s->cert != NULL)) 
 				{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates.
 				 * To add such support, one needs to add
 				 * code that checks for appropriate 
 				 * conditions and sets ecdh_clnt_cert to 1.
 				 * For example, the cert have an ECC
 				 * key on the same curve as the server's
 				 * and the key should be authorized for
 				 * key agreement.
 				 *
 				 * One also needs to add code in ssl3_connect
 				 * to skip sending the certificate verify
 				 * message.
 				 *
 				 * if ((s->cert->key->privatekey != NULL) &&
 				 *     (s->cert->key->privatekey->type ==
 				 *      EVP_PKEY_EC) && ...)
 				 * ecdh_clnt_cert = 1;
 				 */
 				}
 
 			if (s->session->sess_cert->peer_ecdh_tmp != NULL)
 				{
 				tkey = s->session->sess_cert->peer_ecdh_tmp;
 				}
 			else
 				{
 				/* Get the Server Public Key from Cert */
 				srvr_pub_pkey = X509_get_pubkey(s->session-> \
 				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
 				if ((srvr_pub_pkey == NULL) ||
 				    (srvr_pub_pkey->type != EVP_PKEY_EC) ||
 				    (srvr_pub_pkey->pkey.ec == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 					    ERR_R_INTERNAL_ERROR);
 					goto err;
 					}
 
 				tkey = srvr_pub_pkey->pkey.ec;
 				}
 
 			srvr_group   = EC_KEY_get0_group(tkey);
 			srvr_ecpoint = EC_KEY_get0_public_key(tkey);
 
 			if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 				    ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((clnt_ecdh=EC_KEY_new()) == NULL) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 			if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 				goto err;
 				}
 			if (ecdh_clnt_cert) 
 				{ 
 				/* Reuse key info from our certificate
 				 * We only need our private key to perform
 				 * the ECDH computation.
 				 */
 				const BIGNUM *priv_key;
 				tkey = s->cert->key->privatekey->pkey.ec;
 				priv_key = EC_KEY_get0_private_key(tkey);
 				if (priv_key == NULL)
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB);
 					goto err;
 					}
 				}
 			else 
 				{
 				/* Generate a new ECDH key pair */
 				if (!(EC_KEY_generate_key(clnt_ecdh)))
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB);
 					goto err;
 					}
 				}
 
 			/* use the 'p' output buffer for the ECDH key, but
 			 * make sure to clear it out afterwards
 			 */
 
 			field_size = EC_GROUP_get_degree(srvr_group);
 			if (field_size <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
 			if (n <= 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 
 				       ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			/* generate master key from the result */
 			s->session->master_key_length = s->method->ssl3_enc \
 			    -> generate_master_secret(s, 
 				s->session->master_key,
 				p, n);
 
 			memset(p, 0, n); /* clean up */
 
 			if (ecdh_clnt_cert) 
 				{
 				/* Send empty client key exch message */
 				n = 0;
 				}
 			else 
 				{
 				/* First check the size of encoding and
 				 * allocate memory accordingly.
 				 */
 				encoded_pt_len = 
 				    EC_POINT_point2oct(srvr_group, 
 					EC_KEY_get0_public_key(clnt_ecdh), 
 					POINT_CONVERSION_UNCOMPRESSED, 
 					NULL, 0, NULL);
 
 				encodedPoint = (unsigned char *) 
 				    OPENSSL_malloc(encoded_pt_len * 
 					sizeof(unsigned char)); 
 				bn_ctx = BN_CTX_new();
 				if ((encodedPoint == NULL) || 
 				    (bn_ctx == NULL)) 
 					{
 					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 					goto err;
 					}
 
 				/* Encode the public key */
 				n = EC_POINT_point2oct(srvr_group, 
 				    EC_KEY_get0_public_key(clnt_ecdh), 
 				    POINT_CONVERSION_UNCOMPRESSED, 
 				    encodedPoint, encoded_pt_len, bn_ctx);
 
 				*p = n; /* length of encoded point */
 				/* Encoded point will be copied here */
 				p += 1; 
 				/* copy the point */
 				memcpy((unsigned char *)p, encodedPoint, n);
 				/* increment n to account for length field */
 				n += 1; 
 				}
 
 			/* Free allocated memory */
 			BN_CTX_free(bn_ctx);
 			if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 			if (clnt_ecdh != NULL) 
 				 EC_KEY_free(clnt_ecdh);
 			EVP_PKEY_free(srvr_pub_pkey);
 			}
 #endif /* !OPENSSL_NO_ECDH */
 		else
 			{
 			ssl3_send_alert(s, SSL3_AL_FATAL,
 			    SSL_AD_HANDSHAKE_FAILURE);
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
 			    ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		
 		*(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_KEY_EXCH_B;
 		/* number of bytes to write */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_CW_KEY_EXCH_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 #ifndef OPENSSL_NO_ECDH
 	BN_CTX_free(bn_ctx);
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	if (clnt_ecdh != NULL) 
 		EC_KEY_free(clnt_ecdh);
 	EVP_PKEY_free(srvr_pub_pkey);
 #endif
 	return(-1);
 	}
 
 int ssl3_send_client_verify(SSL *s)
 	{
 	unsigned char *p,*d;
 	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	EVP_PKEY *pkey;
 #ifndef OPENSSL_NO_RSA
 	unsigned u=0;
 #endif
 	unsigned long n;
 #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
 	int j;
 #endif
 
 	if (s->state == SSL3_ST_CW_CERT_VRFY_A)
 		{
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 		pkey=s->cert->key->privatekey;
 
 		s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
 			&(data[MD5_DIGEST_LENGTH]));
 
 #ifndef OPENSSL_NO_RSA
 		if (pkey->type == EVP_PKEY_RSA)
 			{
 			s->method->ssl3_enc->cert_verify_mac(s,
 				&(s->s3->finish_dgst1),&(data[0]));
 			if (RSA_sign(NID_md5_sha1, data,
 					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0 )
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
 				goto err;
 				}
 			s2n(u,p);
 			n=u+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DSA
 			if (pkey->type == EVP_PKEY_DSA)
 			{
 			if (!DSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.dsa))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 			if (pkey->type == EVP_PKEY_EC)
 			{
 			if (!ECDSA_sign(pkey->save_type,
 				&(data[MD5_DIGEST_LENGTH]),
 				SHA_DIGEST_LENGTH,&(p[2]),
 				(unsigned int *)&j,pkey->pkey.ec))
 				{
 				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
 				    ERR_R_ECDSA_LIB);
 				goto err;
 				}
 			s2n(j,p);
 			n=j+2;
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
 			goto err;
 			}
 		*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
 		l2n3(n,d);
 
 		s->state=SSL3_ST_CW_CERT_VRFY_B;
 		s->init_num=(int)n+4;
 		s->init_off=0;
 		}
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_send_client_certificate(SSL *s)
 	{
 	X509 *x509=NULL;
 	EVP_PKEY *pkey=NULL;
 	int i;
 	unsigned long l;
 
 	if (s->state ==	SSL3_ST_CW_CERT_A)
 		{
 		if ((s->cert == NULL) ||
 			(s->cert->key->x509 == NULL) ||
 			(s->cert->key->privatekey == NULL))
 			s->state=SSL3_ST_CW_CERT_B;
 		else
 			s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	/* We need to get a client cert */
 	if (s->state == SSL3_ST_CW_CERT_B)
 		{
 		/* If we get an error, we need to
 		 * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
 		 * We then get retied later */
 		i=0;
 		i = ssl_do_client_cert_cb(s, &x509, &pkey);
 		if (i < 0)
 			{
 			s->rwstate=SSL_X509_LOOKUP;
 			return(-1);
 			}
 		s->rwstate=SSL_NOTHING;
 		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
 			{
 			s->state=SSL3_ST_CW_CERT_B;
 			if (	!SSL_use_certificate(s,x509) ||
 				!SSL_use_PrivateKey(s,pkey))
 				i=0;
 			}
 		else if (i == 1)
 			{
 			i=0;
 			SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
 			}
 
 		if (x509 != NULL) X509_free(x509);
 		if (pkey != NULL) EVP_PKEY_free(pkey);
 		if (i == 0)
 			{
 			if (s->version == SSL3_VERSION)
 				{
 				s->s3->tmp.cert_req=0;
 				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
 				return(1);
 				}
 			else
 				{
 				s->s3->tmp.cert_req=2;
 				}
 			}
 
 		/* Ok, we have a cert */
 		s->state=SSL3_ST_CW_CERT_C;
 		}
 
 	if (s->state == SSL3_ST_CW_CERT_C)
 		{
 		s->state=SSL3_ST_CW_CERT_D;
 		l=ssl3_output_cert_chain(s,
 			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509);
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 	/* SSL3_ST_CW_CERT_D */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 #define has_bits(i,m)	(((i)&(m)) == (m))
 
 int ssl3_check_cert_and_algorithm(SSL *s)
 	{
 	int i,idx;
 	long algs;
 	EVP_PKEY *pkey=NULL;
 	SESS_CERT *sc;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh;
 #endif
 
 	sc=s->session->sess_cert;
 
 	algs=s->s3->tmp.new_cipher->algorithms;
 
 	/* we don't have a certificate */
 	if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
 		return(1);
 
 	if (sc == NULL)
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
 		goto err;
 		}
 
 #ifndef OPENSSL_NO_RSA
 	rsa=s->session->sess_cert->peer_rsa_tmp;
 #endif
 #ifndef OPENSSL_NO_DH
 	dh=s->session->sess_cert->peer_dh_tmp;
 #endif
 
 	/* This is the passed certificate */
 
 	idx=sc->peer_cert_type;
 #ifndef OPENSSL_NO_ECDH
 	if (idx == SSL_PKEY_ECC)
 		{
 		if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
 		    s->s3->tmp.new_cipher) == 0) 
 			{ /* check failed */
 			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
 			goto f_err;			
 			}
 		else 
 			{
 			return 1;
 			}
 		}
 #endif
 	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
 	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
 	EVP_PKEY_free(pkey);
 
 	
 	/* Check that we have a certificate if we require one */
 	if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_DSA
 	else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
 		goto f_err;
 		}
 #endif
 #ifndef OPENSSL_NO_RSA
 	if ((algs & SSL_kRSA) &&
 		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
 		goto f_err;
 		}
 #endif
 #ifndef OPENSSL_NO_DH
 	if ((algs & SSL_kEDH) &&
 		!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
 		goto f_err;
 		}
 	else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
 		goto f_err;
 		}
 #ifndef OPENSSL_NO_DSA
 	else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
 		goto f_err;
 		}
 #endif
 #endif
 
 	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
 		{
 #ifndef OPENSSL_NO_RSA
 		if (algs & SSL_kRSA)
 			{
 			if (rsa == NULL
 			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
 				{
 				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
 				goto f_err;
 				}
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DH
 			if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 			    {
 			    if (dh == NULL
 				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
 				{
 				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
 				goto f_err;
 				}
 			}
 		else
 #endif
 			{
 			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		}
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 err:
 	return(0);
 	}
 
 
 #ifndef OPENSSL_NO_ECDH
 /* This is the complement of nid2curve_id in s3_srvr.c. */
 static int curve_id2nid(int curve_id)
 {
 	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
 	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
 	static int nid_list[26] =
 	{
 		0,
 		NID_sect163k1, /* sect163k1 (1) */
 		NID_sect163r1, /* sect163r1 (2) */
 		NID_sect163r2, /* sect163r2 (3) */
 		NID_sect193r1, /* sect193r1 (4) */ 
 		NID_sect193r2, /* sect193r2 (5) */ 
 		NID_sect233k1, /* sect233k1 (6) */
 		NID_sect233r1, /* sect233r1 (7) */ 
 		NID_sect239k1, /* sect239k1 (8) */ 
 		NID_sect283k1, /* sect283k1 (9) */
 		NID_sect283r1, /* sect283r1 (10) */ 
 		NID_sect409k1, /* sect409k1 (11) */ 
 		NID_sect409r1, /* sect409r1 (12) */
 		NID_sect571k1, /* sect571k1 (13) */ 
 		NID_sect571r1, /* sect571r1 (14) */ 
 		NID_secp160k1, /* secp160k1 (15) */
 		NID_secp160r1, /* secp160r1 (16) */ 
 		NID_secp160r2, /* secp160r2 (17) */ 
 		NID_secp192k1, /* secp192k1 (18) */
 		NID_X9_62_prime192v1, /* secp192r1 (19) */ 
 		NID_secp224k1, /* secp224k1 (20) */ 
 		NID_secp224r1, /* secp224r1 (21) */
 		NID_secp256k1, /* secp256k1 (22) */ 
 		NID_X9_62_prime256v1, /* secp256r1 (23) */ 
 		NID_secp384r1, /* secp384r1 (24) */
 		NID_secp521r1  /* secp521r1 (25) */	
 	};
 	
 	if ((curve_id < 1) || (curve_id > 25)) return 0;
 
 	return nid_list[curve_id];
 }
 #endif
 
 /* Check to see if handshake is full or resumed. Usually this is just a
  * case of checking to see if a cache hit has occurred. In the case of
  * session tickets we have to check the next message to be sure.
  */
 
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_check_finished(SSL *s)
 	{
 	int ok;
 	long n;
 	/* If we have no ticket or session ID is non-zero length (a match of
 	 * a non-zero session length would never reach here) it cannot be a
 	 * resumed session.
 	 */
 	if (!s->session->tlsext_tick || s->session->session_id_length)
 		return 1;
 	/* this function is called when we really expect a Certificate
 	 * message, so permit appropriate message length */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_CR_CERT_A,
 		SSL3_ST_CR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 	s->s3->tmp.reuse_message = 1;
 	if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
 		|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
 		return 2;
 
 	return 1;
 	}
 #endif
 
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 	{
 	int i = 0;
 #ifndef OPENSSL_NO_ENGINE
 	if (s->ctx->client_cert_engine)
 		{
 		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
 						SSL_get_client_CA_list(s),
 						px509, ppkey, NULL, NULL, NULL);
 		if (i != 0)
 			return i;
 		}
 #endif
 	if (s->ctx->client_cert_cb)
 		i = s->ctx->client_cert_cb(s,px509,ppkey);
 	return i;
 	}
Index: releng/9.3/crypto/openssl/ssl/s3_srvr.c
===================================================================
--- releng/9.3/crypto/openssl/ssl/s3_srvr.c	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/s3_srvr.c	(revision 284295)
@@ -1,2914 +1,2924 @@
 /* ssl/s3_srvr.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  *
  * Portions of the attached software ("Contribution") are developed by 
  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  *
  * The Contribution is licensed pursuant to the OpenSSL open source
  * license provided above.
  *
  * ECC cipher suite support in OpenSSL originally written by
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
 
 #define REUSE_CIPHER_BUG
 #define NETSCAPE_HANG_BUG
 
 #include 
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
 #include "../crypto/constant_time_locl.h"
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_DH
 #include 
 #endif
 #include 
 #ifndef OPENSSL_NO_KRB5
 #include 
 #endif
 #include 
 
 static SSL_METHOD *ssl3_get_server_method(int ver);
 #ifndef OPENSSL_NO_ECDH
 static int nid2curve_id(int nid);
 #endif
 
 static SSL_METHOD *ssl3_get_server_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
 		return(SSLv3_server_method());
 	else
 		return(NULL);
 	}
 
 IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
 			ssl3_accept,
 			ssl_undefined_function,
 			ssl3_get_server_method)
 
 int ssl3_accept(SSL *s)
 	{
 	BUF_MEM *buf;
 	unsigned long l,Time=(unsigned long)time(NULL);
 	void (*cb)(const SSL *ssl,int type,int val)=NULL;
 	int ret= -1;
 	int new_state,state,skip=0;
 
 	RAND_add(&Time,sizeof(Time),0);
 	ERR_clear_error();
 	clear_sys_error();
 
 	if (s->info_callback != NULL)
 		cb=s->info_callback;
 	else if (s->ctx->info_callback != NULL)
 		cb=s->ctx->info_callback;
 
 	/* init things to blank */
 	s->in_handshake++;
 	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
 
 	if (s->cert == NULL)
 		{
 		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
 		return(-1);
 		}
 
 	for (;;)
 		{
 		state=s->state;
 
 		switch (s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
 			s->new_session=1;
 			/* s->state=SSL_ST_ACCEPT; */
 
 		case SSL_ST_BEFORE:
 		case SSL_ST_ACCEPT:
 		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
 		case SSL_ST_OK|SSL_ST_ACCEPT:
 
 			s->server=1;
 			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
 			if ((s->version>>8) != 3)
 				{
 				SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
 				return -1;
 				}
 			s->type=SSL_ST_ACCEPT;
 
 			if (s->init_buf == NULL)
 				{
 				if ((buf=BUF_MEM_new()) == NULL)
 					{
 					ret= -1;
 					goto end;
 					}
 				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
 					{
 					ret= -1;
 					goto end;
 					}
 				s->init_buf=buf;
 				}
 
 			if (!ssl3_setup_buffers(s))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			s->init_num=0;
 			s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
 
 			if (s->state != SSL_ST_RENEGOTIATE)
 				{
 				/* Ok, we now need to push on a buffering BIO so that
 				 * the output is sent in a way that TCP likes :-)
 				 */
 				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
 				
 				ssl3_init_finished_mac(s);
 				s->state=SSL3_ST_SR_CLNT_HELLO_A;
 				s->ctx->stats.sess_accept++;
 				}
 			else if (!s->s3->send_connection_binding &&
 				!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
 				{
 				/* Server attempting to renegotiate with
 				 * client that doesn't support secure
 				 * renegotiation.
 				 */
 				SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
 				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
 				ret = -1;
 				goto end;
 				}
 			else
 				{
 				/* s->state == SSL_ST_RENEGOTIATE,
 				 * we will just send a HelloRequest */
 				s->ctx->stats.sess_accept_renegotiate++;
 				s->state=SSL3_ST_SW_HELLO_REQ_A;
 				}
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_A:
 		case SSL3_ST_SW_HELLO_REQ_B:
 
 			s->shutdown=0;
 			ret=ssl3_send_hello_request(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 
 			ssl3_init_finished_mac(s);
 			break;
 
 		case SSL3_ST_SW_HELLO_REQ_C:
 			s->state=SSL_ST_OK;
 			break;
 
 		case SSL3_ST_SR_CLNT_HELLO_A:
 		case SSL3_ST_SR_CLNT_HELLO_B:
 		case SSL3_ST_SR_CLNT_HELLO_C:
 
 			s->shutdown=0;
 			ret=ssl3_get_client_hello(s);
 			if (ret <= 0) goto end;
 			s->new_session = 2;
 			s->state=SSL3_ST_SW_SRVR_HELLO_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_SRVR_HELLO_A:
 		case SSL3_ST_SW_SRVR_HELLO_B:
 			ret=ssl3_send_server_hello(s);
 			if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 			if (s->hit)
 				{
 				if (s->tlsext_ticket_expected)
 					s->state=SSL3_ST_SW_SESSION_TICKET_A;
 				else
 					s->state=SSL3_ST_SW_CHANGE_A;
 				}
 #else
 			if (s->hit)
 					s->state=SSL3_ST_SW_CHANGE_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CERT_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_A:
 		case SSL3_ST_SW_CERT_B:
 			/* Check if it is anon DH or anon ECDH or KRB5 */
 			if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
 				&& !(s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
 				{
 				ret=ssl3_send_server_certificate(s);
 				if (ret <= 0) goto end;
 #ifndef OPENSSL_NO_TLSEXT
 				if (s->tlsext_status_expected)
 					s->state=SSL3_ST_SW_CERT_STATUS_A;
 				else
 					s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 			else
 				{
 				skip = 1;
 				s->state=SSL3_ST_SW_KEY_EXCH_A;
 				}
 #else
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 #endif
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_KEY_EXCH_A:
 		case SSL3_ST_SW_KEY_EXCH_B:
 			l=s->s3->tmp.new_cipher->algorithms;
 
 			/* clear this, it may get reset by
 			 * send_server_key_exchange */
 			s->s3->tmp.use_rsa_tmp=0;
 
 
 			/* only send if a DH key exchange, fortezza or
 			 * RSA but we have a sign only certificate
 			 *
 			 * For ECC ciphersuites, we send a serverKeyExchange
 			 * message only if the cipher suite is either
 			 * ECDH-anon or ECDHE. In other cases, the
 			 * server certificate contains the server's 
 			 * public key for key exchange.
 			 */
 			if ((l & SSL_kECDHE)
 			    || (l & (SSL_DH|SSL_kFZA))
 			    || ((l & SSL_kRSA)
 				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
 				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
 					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
 					)
 				    )
 				)
 			    )
 				{
 				ret=ssl3_send_server_key_exchange(s);
 				if (ret <= 0) goto end;
 				}
 			else
 				skip=1;
 
 			s->state=SSL3_ST_SW_CERT_REQ_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_REQ_A:
 		case SSL3_ST_SW_CERT_REQ_B:
 			if (/* don't request cert unless asked for it: */
 				!(s->verify_mode & SSL_VERIFY_PEER) ||
 				/* if SSL_VERIFY_CLIENT_ONCE is set,
 				 * don't request cert during re-negotiation: */
 				((s->session->peer != NULL) &&
 				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
 				/* never request cert in anonymous ciphersuites
 				 * (see section "Certificate request" in SSL 3 drafts
 				 * and in RFC 2246): */
 				((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&
 				 /* ... except when the application insists on verification
 				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
 				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
                                  /* never request cert in Kerberos ciphersuites */
                                 (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
 				{
 				/* no cert request */
 				skip=1;
 				s->s3->tmp.cert_request=0;
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 				}
 			else
 				{
 				s->s3->tmp.cert_request=1;
 				ret=ssl3_send_certificate_request(s);
 				if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
 				s->state=SSL3_ST_SW_SRVR_DONE_A;
 #else
 				s->state=SSL3_ST_SW_FLUSH;
 				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 #endif
 				s->init_num=0;
 				}
 			break;
 
 		case SSL3_ST_SW_SRVR_DONE_A:
 		case SSL3_ST_SW_SRVR_DONE_B:
 			ret=ssl3_send_server_done(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
 			s->state=SSL3_ST_SW_FLUSH;
 			s->init_num=0;
 			break;
 		
 		case SSL3_ST_SW_FLUSH:
 
 			/* This code originally checked to see if
 			 * any data was pending using BIO_CTRL_INFO
 			 * and then flushed. This caused problems
 			 * as documented in PR#1939. The proposed
 			 * fix doesn't completely resolve this issue
 			 * as buggy implementations of BIO_CTRL_PENDING
 			 * still exist. So instead we just flush
 			 * unconditionally.
 			 */
 
 			s->rwstate=SSL_WRITING;
 			if (BIO_flush(s->wbio) <= 0)
 				{
 				ret= -1;
 				goto end;
 				}
 			s->rwstate=SSL_NOTHING;
 
 			s->state=s->s3->tmp.next_state;
 			break;
 
 		case SSL3_ST_SR_CERT_A:
 		case SSL3_ST_SR_CERT_B:
 			/* Check for second client hello (MS SGC) */
 			ret = ssl3_check_client_hello(s);
 			if (ret <= 0)
 				goto end;
 			if (ret == 2)
 				s->state = SSL3_ST_SR_CLNT_HELLO_C;
 			else {
 				if (s->s3->tmp.cert_request)
 					{
 					ret=ssl3_get_client_certificate(s);
 					if (ret <= 0) goto end;
 					}
 				s->init_num=0;
 				s->state=SSL3_ST_SR_KEY_EXCH_A;
 			}
 			break;
 
 		case SSL3_ST_SR_KEY_EXCH_A:
 		case SSL3_ST_SR_KEY_EXCH_B:
 			ret=ssl3_get_client_key_exchange(s);
 			if (ret <= 0) 
 				goto end;
 			if (ret == 2)
 				{
 				/* For the ECDH ciphersuites when
 				 * the client sends its ECDH pub key in
 				 * a certificate, the CertificateVerify
 				 * message is not sent.
 				 */
 				s->state=SSL3_ST_SR_FINISHED_A;
 				s->init_num = 0;
 				}
 			else   
 				{
 				s->state=SSL3_ST_SR_CERT_VRFY_A;
 				s->init_num=0;
 
 				/* We need to get hashes here so if there is
 				 * a client cert, it can be verified
 				 */ 
 				s->method->ssl3_enc->cert_verify_mac(s,
 				    &(s->s3->finish_dgst1),
 				    &(s->s3->tmp.cert_verify_md[0]));
 				s->method->ssl3_enc->cert_verify_mac(s,
 				    &(s->s3->finish_dgst2),
 				    &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
 				}
 			break;
 
 		case SSL3_ST_SR_CERT_VRFY_A:
 		case SSL3_ST_SR_CERT_VRFY_B:
 
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			/* we should decide if we expected this one */
 			ret=ssl3_get_cert_verify(s);
 			if (ret <= 0) goto end;
 
 			s->state=SSL3_ST_SR_FINISHED_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SR_FINISHED_A:
 		case SSL3_ST_SR_FINISHED_B:
 			s->s3->flags |= SSL3_FLAGS_CCS_OK;
 			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
 				SSL3_ST_SR_FINISHED_B);
 			if (ret <= 0) goto end;
 			if (s->hit)
 				s->state=SSL_ST_OK;
 #ifndef OPENSSL_NO_TLSEXT
 			else if (s->tlsext_ticket_expected)
 				s->state=SSL3_ST_SW_SESSION_TICKET_A;
 #endif
 			else
 				s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 #ifndef OPENSSL_NO_TLSEXT
 		case SSL3_ST_SW_SESSION_TICKET_A:
 		case SSL3_ST_SW_SESSION_TICKET_B:
 			ret=ssl3_send_newsession_ticket(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_CHANGE_A;
 			s->init_num=0;
 			break;
 
 		case SSL3_ST_SW_CERT_STATUS_A:
 		case SSL3_ST_SW_CERT_STATUS_B:
 			ret=ssl3_send_cert_status(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_KEY_EXCH_A;
 			s->init_num=0;
 			break;
 
 #endif
 
 		case SSL3_ST_SW_CHANGE_A:
 		case SSL3_ST_SW_CHANGE_B:
 
 			s->session->cipher=s->s3->tmp.new_cipher;
 			if (!s->method->ssl3_enc->setup_key_block(s))
 				{ ret= -1; goto end; }
 
 			ret=ssl3_send_change_cipher_spec(s,
 				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
 
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FINISHED_A;
 			s->init_num=0;
 
 			if (!s->method->ssl3_enc->change_cipher_state(s,
 				SSL3_CHANGE_CIPHER_SERVER_WRITE))
 				{
 				ret= -1;
 				goto end;
 				}
 
 			break;
 
 		case SSL3_ST_SW_FINISHED_A:
 		case SSL3_ST_SW_FINISHED_B:
 			ret=ssl3_send_finished(s,
 				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
 				s->method->ssl3_enc->server_finished_label,
 				s->method->ssl3_enc->server_finished_label_len);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
 				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
 			else
 				s->s3->tmp.next_state=SSL_ST_OK;
 			s->init_num=0;
 			break;
 
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
 
 			BUF_MEM_free(s->init_buf);
 			s->init_buf=NULL;
 
 			/* remove buffering on output */
 			ssl_free_wbio_buffer(s);
 
 			s->init_num=0;
 
 			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
 				{
 				/* actually not necessarily a 'new' session unless
 				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 				
 				s->new_session=0;
 				
 				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
 				
 				s->ctx->stats.sess_accept_good++;
 				/* s->server=1; */
 				s->handshake_func=ssl3_accept;
 
 				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
 				}
 			
 			ret = 1;
 			goto end;
 			/* break; */
 
 		default:
 			SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE);
 			ret= -1;
 			goto end;
 			/* break; */
 			}
 		
 		if (!s->s3->tmp.reuse_message && !skip)
 			{
 			if (s->debug)
 				{
 				if ((ret=BIO_flush(s->wbio)) <= 0)
 					goto end;
 				}
 
 
 			if ((cb != NULL) && (s->state != state))
 				{
 				new_state=s->state;
 				s->state=state;
 				cb(s,SSL_CB_ACCEPT_LOOP,1);
 				s->state=new_state;
 				}
 			}
 		skip=0;
 		}
 end:
 	/* BIO_flush(s->wbio); */
 
 	s->in_handshake--;
 	if (cb != NULL)
 		cb(s,SSL_CB_ACCEPT_EXIT,ret);
 	return(ret);
 	}
 
 int ssl3_send_hello_request(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_HELLO_REQ_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 		*(p++)=SSL3_MT_HELLO_REQUEST;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_HELLO_REQ_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_HELLO_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_check_client_hello(SSL *s)
 	{
 	int ok;
 	long n;
 
 	/* this function is called when we really expect a Certificate message,
 	 * so permit appropriate message length */
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 	if (!ok) return((int)n);
 	s->s3->tmp.reuse_message = 1;
 	if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
 		{
 		/* We only allow the client to restart the handshake once per
 		 * negotiation. */
 		if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
 			{
 			SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
 			return -1;
 			}
 		/* Throw away what we have done so far in the current handshake,
 		 * which will now be aborted. (A full SSL_clear would be too much.) */
 #ifndef OPENSSL_NO_DH
 		if (s->s3->tmp.dh != NULL)
 			{
 			DH_free(s->s3->tmp.dh);
 			s->s3->tmp.dh = NULL;
 			}
 #endif
 #ifndef OPENSSL_NO_ECDH
 		if (s->s3->tmp.ecdh != NULL)
 			{
 			EC_KEY_free(s->s3->tmp.ecdh);
 			s->s3->tmp.ecdh = NULL;
 			}
 #endif
 		s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
 		return 2;
 		}
 	return 1;
 }
 
 int ssl3_get_client_hello(SSL *s)
 	{
 	int i,j,ok,al,ret= -1;
 	unsigned int cookie_len;
 	long n;
 	unsigned long id;
 	unsigned char *p,*d,*q;
 	SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
 	SSL_COMP *comp=NULL;
 #endif
 	STACK_OF(SSL_CIPHER) *ciphers=NULL;
 
 	/* We do this so that we will respond with our native type.
 	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
 	 * This down switching should be handled by a different method.
 	 * If we are SSLv3, we will respond with SSLv3, even if prompted with
 	 * TLSv1.
 	 */
 	if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
 		{
 		s->state=SSL3_ST_SR_CLNT_HELLO_B;
 		}
 	s->first_packet=1;
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CLNT_HELLO_B,
 		SSL3_ST_SR_CLNT_HELLO_C,
 		SSL3_MT_CLIENT_HELLO,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 	s->first_packet=0;
 	d=p=(unsigned char *)s->init_msg;
 
 	/* use version from inside client hello, not from record header
 	 * (may differ: see RFC 2246, Appendix E, second paragraph) */
 	s->client_version=(((int)p[0])<<8)|(int)p[1];
 	p+=2;
 
 	if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
 	    (s->version != DTLS1_VERSION && s->client_version < s->version))
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
 		if ((s->client_version>>8) == SSL3_VERSION_MAJOR) 
 			{
 			/* similar to ssl3_get_record, send alert using remote version number */
 			s->version = s->client_version;
 			}
 		al = SSL_AD_PROTOCOL_VERSION;
 		goto f_err;
 		}
 
 	/* If we require cookies and this ClientHello doesn't
 	 * contain one, just return since we do not want to
 	 * allocate any memory yet. So check cookie length...
 	 */
 	if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
 		{
 		unsigned int session_length, cookie_length;
 		
 		session_length = *(p + SSL3_RANDOM_SIZE);
 		cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
 
 		if (cookie_length == 0)
 			return 1;
 		}
 
 	/* load the client random */
 	memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
 	p+=SSL3_RANDOM_SIZE;
 
 	/* get the session-id */
 	j= *(p++);
 
 	s->hit=0;
 	/* Versions before 0.9.7 always allow session reuse during renegotiation
 	 * (i.e. when s->new_session is true), option
 	 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
 	 * Maybe this optional behaviour should always have been the default,
 	 * but we cannot safely change the default behaviour (or new applications
 	 * might be written that become totally unsecure when compiled with
 	 * an earlier library version)
 	 */
 	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
 		{
 		if (!ssl_get_new_session(s,1))
 			goto err;
 		}
 	else
 		{
 		i=ssl_get_prev_session(s, p, j, d + n);
 		if (i == 1)
 			{ /* previous session */
 			s->hit=1;
 			}
 		else if (i == -1)
 			goto err;
 		else /* i == 0 */
 			{
 			if (!ssl_get_new_session(s,1))
 				goto err;
 			}
 		}
 
 	p+=j;
 
 	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
 		{
 		/* cookie stuff */
 		cookie_len = *(p++);
 
 		/* 
 		 * The ClientHello may contain a cookie even if the
 		 * HelloVerify message has not been sent--make sure that it
 		 * does not cause an overflow.
 		 */
 		if ( cookie_len > sizeof(s->d1->rcvd_cookie))
 			{
 			/* too much data */
 			al = SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
 			goto f_err;
 			}
 
 		/* verify the cookie if appropriate option is set. */
 		if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
 			cookie_len > 0)
 			{
 			memcpy(s->d1->rcvd_cookie, p, cookie_len);
 
 			if ( s->ctx->app_verify_cookie_cb != NULL)
 				{
 				if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
 					cookie_len) == 0)
 					{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 					}
 				/* else cookie verification succeeded */
 				}
 			else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, 
 						  s->d1->cookie_len) != 0) /* default verification */
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
 						SSL_R_COOKIE_MISMATCH);
 					goto f_err;
 				}
 
 			ret = 2;
 			}
 
 		p += cookie_len;
 		}
 
 	n2s(p,i);
 	if ((i == 0) && (j != 0))
 		{
 		/* we need a cipher if we are not resuming a session */
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED);
 		goto f_err;
 		}
 	if ((p+i) >= (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))
 		== NULL))
 		{
 		goto err;
 		}
 	p+=i;
 
 	/* If it is a hit, check that the cipher is in the list */
 	if ((s->hit) && (i > 0))
 		{
 		j=0;
 		id=s->session->cipher->id;
 
 #ifdef CIPHER_DEBUG
 		printf("client sent %d ciphers\n",sk_num(ciphers));
 #endif
 		for (i=0; iid == id)
 				{
 				j=1;
 				break;
 				}
 			}
 /* Disabled because it can be used in a ciphersuite downgrade
  * attack: CVE-2010-4180.
  */
 #if 0
 		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
 			{
 			/* Special case as client bug workaround: the previously used cipher may
 			 * not be in the current list, the client instead might be trying to
 			 * continue using a cipher that before wasn't chosen due to server
 			 * preferences.  We'll have to reject the connection if the cipher is not
 			 * enabled, though. */
 			c = sk_SSL_CIPHER_value(ciphers, 0);
 			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0)
 				{
 				s->session->cipher = c;
 				j = 1;
 				}
 			}
 #endif
 		if (j == 0)
 			{
 			/* we need to have the cipher in the cipher
 			 * list if we are asked to reuse it */
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING);
 			goto f_err;
 			}
 		}
 
 	/* compression */
 	i= *(p++);
 	if ((p+i) > (d+n))
 		{
 		/* not enough data */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	q=p;
 	for (j=0; j= i)
 		{
 		/* no compress */
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED);
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions*/
 	if (s->version >= SSL3_VERSION)
 		{
 		if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
 			{
 			/* 'al' set by ssl_parse_clienthello_tlsext */
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
 			goto f_err;
 			}
 		}
 		if (ssl_check_clienthello_tlsext_early(s) <= 0) {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 		}
 #endif
 	/* Worst case, we will use the NULL compression, but if we have other
 	 * options, we will now look for them.  We have i-1 compression
 	 * algorithms from the client, starting at q. */
 	s->s3->tmp.new_compression=NULL;
 #ifndef OPENSSL_NO_COMP
 	if (s->ctx->comp_methods != NULL)
 		{ /* See if we have a match */
 		int m,nn,o,v,done=0;
 
 		nn=sk_SSL_COMP_num(s->ctx->comp_methods);
 		for (m=0; mctx->comp_methods,m);
 			v=comp->id;
 			for (o=0; os3->tmp.new_compression=comp;
 		else
 			comp=NULL;
 		}
 #endif
 
 	/* TLS does not mind if there is extra stuff */
 #if 0   /* SSL 3.0 does not mind either, so we should disable this test
          * (was enabled in 0.9.6d through 0.9.6j and 0.9.7 through 0.9.7b,
          * in earlier SSLeay/OpenSSL releases this test existed but was buggy) */
 	if (s->version == SSL3_VERSION)
 		{
 		if (p < (d+n))
 			{
 			/* wrong number of bytes,
 			 * there could be more to follow */
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		}
 #endif
 
 	/* Given s->session->ciphers and SSL_get_ciphers, we must
 	 * pick a cipher */
 
 	if (!s->hit)
 		{
 #ifdef OPENSSL_NO_COMP
 		s->session->compress_meth=0;
 #else
 		s->session->compress_meth=(comp == NULL)?0:comp->id;
 #endif
 		if (s->session->ciphers != NULL)
 			sk_SSL_CIPHER_free(s->session->ciphers);
 		s->session->ciphers=ciphers;
 		if (ciphers == NULL)
 			{
 			al=SSL_AD_ILLEGAL_PARAMETER;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED);
 			goto f_err;
 			}
 		ciphers=NULL;
 		c=ssl3_choose_cipher(s,s->session->ciphers,
 				     SSL_get_ciphers(s));
 
 		if (c == NULL)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
 			goto f_err;
 			}
 		s->s3->tmp.new_cipher=c;
 		}
 	else
 		{
 		/* Session-id reuse */
 #ifdef REUSE_CIPHER_BUG
 		STACK_OF(SSL_CIPHER) *sk;
 		SSL_CIPHER *nc=NULL;
 		SSL_CIPHER *ec=NULL;
 
 		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
 			{
 			sk=s->session->ciphers;
 			for (i=0; ialgorithms & SSL_eNULL)
 					nc=c;
 				if (SSL_C_IS_EXPORT(c))
 					ec=c;
 				}
 			if (nc != NULL)
 				s->s3->tmp.new_cipher=nc;
 			else if (ec != NULL)
 				s->s3->tmp.new_cipher=ec;
 			else
 				s->s3->tmp.new_cipher=s->session->cipher;
 			}
 		else
 #endif
 		s->s3->tmp.new_cipher=s->session->cipher;
 		}
 	
 	/* we now have the following setup. 
 	 * client_random
 	 * cipher_list 		- our prefered list of ciphers
 	 * ciphers 		- the clients prefered list of ciphers
 	 * compression		- basically ignored right now
 	 * ssl version is set	- sslv3
 	 * s->session		- The ssl session has been setup.
 	 * s->hit		- session reuse flag
 	 * s->tmp.new_cipher	- the new cipher to use.
 	 */
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* Handles TLS extensions that we couldn't check earlier */
 	if (s->version >= SSL3_VERSION)
 		{
 		if (ssl_check_clienthello_tlsext_late(s) <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
 			goto err;
 			}
 		}
 #endif
 
 	if (ret < 0) ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
 	return(ret);
 	}
 
 int ssl3_send_server_hello(SSL *s)
 	{
 	unsigned char *buf;
 	unsigned char *p,*d;
 	int i,sl;
 	unsigned long l,Time;
 
 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
 		{
 		buf=(unsigned char *)s->init_buf->data;
 		p=s->s3->server_random;
 		Time=(unsigned long)time(NULL);			/* Time */
 		l2n(Time,p);
 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
 			return -1;
 		/* Do the message type and length last */
 		d=p= &(buf[4]);
 
 		*(p++)=s->version>>8;
 		*(p++)=s->version&0xff;
 
 		/* Random stuff */
 		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
 		p+=SSL3_RANDOM_SIZE;
 
 		/* now in theory we have 3 options to sending back the
 		 * session id.  If it is a re-use, we send back the
 		 * old session-id, if it is a new session, we send
 		 * back the new session-id or we send back a 0 length
 		 * session-id if we want it to be single use.
 		 * Currently I will not implement the '0' length session-id
 		 * 12-Jan-98 - I'll now support the '0' length stuff.
 		 *
 		 * We also have an additional case where stateless session
 		 * resumption is successful: we always send back the old
 		 * session id. In this case s->hit is non zero: this can
 		 * only happen if stateless session resumption is succesful
 		 * if session caching is disabled so existing functionality
 		 * is unaffected.
 		 */
 		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
 			&& !s->hit)
 			s->session->session_id_length=0;
 
 		sl=s->session->session_id_length;
 		if (sl > (int)sizeof(s->session->session_id))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 		*(p++)=sl;
 		memcpy(p,s->session->session_id,sl);
 		p+=sl;
 
 		/* put the cipher */
 		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
 		p+=i;
 
 		/* put the compression method */
 #ifdef OPENSSL_NO_COMP
 			*(p++)=0;
 #else
 		if (s->s3->tmp.new_compression == NULL)
 			*(p++)=0;
 		else
 			*(p++)=s->s3->tmp.new_compression->id;
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
 			return -1;
 			}
 #endif
 		/* do the header */
 		l=(p-d);
 		d=buf;
 		*(d++)=SSL3_MT_SERVER_HELLO;
 		l2n3(l,d);
 
 		s->state=SSL3_ST_SW_SRVR_HELLO_B;
 		/* number of bytes to write */
 		s->init_num=p-buf;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_HELLO_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_done(SSL *s)
 	{
 	unsigned char *p;
 
 	if (s->state == SSL3_ST_SW_SRVR_DONE_A)
 		{
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 
 		s->state=SSL3_ST_SW_SRVR_DONE_B;
 		/* number of bytes to write */
 		s->init_num=4;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_SRVR_DONE_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_server_key_exchange(SSL *s)
 	{
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	int j,num;
 	RSA *rsa;
 	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
 	unsigned int u;
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh=NULL,*dhp;
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh=NULL, *ecdhp;
 	unsigned char *encodedPoint = NULL;
 	int encodedlen = 0;
 	int curve_id = 0;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 	EVP_PKEY *pkey;
 	unsigned char *p,*d;
 	int al,i;
 	unsigned long type;
 	int n;
 	CERT *cert;
 	BIGNUM *r[4];
 	int nr[4],kn;
 	BUF_MEM *buf;
 	EVP_MD_CTX md_ctx;
 
 	EVP_MD_CTX_init(&md_ctx);
 	if (s->state == SSL3_ST_SW_KEY_EXCH_A)
 		{
 		type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;
 		cert=s->cert;
 
 		buf=s->init_buf;
 
 		r[0]=r[1]=r[2]=r[3]=NULL;
 		n=0;
 #ifndef OPENSSL_NO_RSA
 		if (type & SSL_kRSA)
 			{
 			rsa=cert->rsa_tmp;
 			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
 				{
 				rsa=s->cert->rsa_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				if(rsa == NULL)
 				{
 					al=SSL_AD_HANDSHAKE_FAILURE;
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
 					goto f_err;
 				}
 				RSA_up_ref(rsa);
 				cert->rsa_tmp=rsa;
 				}
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
 				goto f_err;
 				}
 			r[0]=rsa->n;
 			r[1]=rsa->e;
 			s->s3->tmp.use_rsa_tmp=1;
 			}
 		else
 #endif
 #ifndef OPENSSL_NO_DH
 			if (type & SSL_kEDH)
 			{
 			dhp=cert->dh_tmp;
 			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
 				dhp=s->cert->dh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 			if (dhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.dh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			if ((dh=DHparams_dup(dhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.dh=dh;
 			if ((dhp->pub_key == NULL ||
 			     dhp->priv_key == NULL ||
 			     (s->options & SSL_OP_SINGLE_DH_USE)))
 				{
 				if(!DH_generate_key(dh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
 					   ERR_R_DH_LIB);
 				    goto err;
 				    }
 				}
 			else
 				{
 				dh->pub_key=BN_dup(dhp->pub_key);
 				dh->priv_key=BN_dup(dhp->priv_key);
 				if ((dh->pub_key == NULL) ||
 					(dh->priv_key == NULL))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
 					goto err;
 					}
 				}
 			r[0]=dh->p;
 			r[1]=dh->g;
 			r[2]=dh->pub_key;
 			}
 		else 
 #endif
 #ifndef OPENSSL_NO_ECDH
 			if (type & SSL_kECDHE)
 			{
 			const EC_GROUP *group;
 
 			ecdhp=cert->ecdh_tmp;
 			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
 				{
 				ecdhp=s->cert->ecdh_tmp_cb(s,
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
 				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
 				}
 			if (ecdhp == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				goto f_err;
 				}
 
 			if (s->s3->tmp.ecdh != NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
 				goto err;
 				}
 
 			/* Duplicate the ECDH structure. */
 			if (ecdhp == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			s->s3->tmp.ecdh=ecdh;
 			if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL) ||
 			    (s->options & SSL_OP_SINGLE_ECDH_USE))
 				{
 				if(!EC_KEY_generate_key(ecdh))
 				    {
 				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				    goto err;
 				    }
 				}
 
 			if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
 			    (EC_KEY_get0_public_key(ecdh)  == NULL) ||
 			    (EC_KEY_get0_private_key(ecdh) == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
 			    (EC_GROUP_get_degree(group) > 163)) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
 				goto err;
 				}
 
 			/* XXX: For now, we only support ephemeral ECDH
 			 * keys over named (not generic) curves. For 
 			 * supported named curves, curve_id is non-zero.
 			 */
 			if ((curve_id = 
 			    nid2curve_id(EC_GROUP_get_curve_name(group)))
 			    == 0)
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
 				goto err;
 				}
 
 			/* Encode the public key.
 			 * First check the size of encoding and
 			 * allocate memory accordingly.
 			 */
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh),
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    NULL, 0, NULL);
 
 			encodedPoint = (unsigned char *) 
 			    OPENSSL_malloc(encodedlen*sizeof(unsigned char)); 
 			bn_ctx = BN_CTX_new();
 			if ((encodedPoint == NULL) || (bn_ctx == NULL))
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
 
 			encodedlen = EC_POINT_point2oct(group, 
 			    EC_KEY_get0_public_key(ecdh), 
 			    POINT_CONVERSION_UNCOMPRESSED, 
 			    encodedPoint, encodedlen, bn_ctx);
 
 			if (encodedlen == 0) 
 				{
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
 				goto err;
 				}
 
 			BN_CTX_free(bn_ctx);  bn_ctx=NULL;
 
 			/* XXX: For now, we only support named (not 
 			 * generic) curves in ECDH ephemeral key exchanges.
 			 * In this situation, we need four additional bytes
 			 * to encode the entire ServerECDHParams
 			 * structure. 
 			 */
 			n = 4 + encodedlen;
 
 			/* We'll generate the serverKeyExchange message
 			 * explicitly so we can set these to NULLs
 			 */
 			r[0]=NULL;
 			r[1]=NULL;
 			r[2]=NULL;
 			r[3]=NULL;
 			}
 		else 
 #endif /* !OPENSSL_NO_ECDH */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
 		for (i=0; r[i] != NULL; i++)
 			{
 			nr[i]=BN_num_bytes(r[i]);
 			n+=2+nr[i];
 			}
 
 		if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
 			{
 			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
 				== NULL)
 				{
 				al=SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 			kn=EVP_PKEY_size(pkey);
 			}
 		else
 			{
 			pkey=NULL;
 			kn=0;
 			}
 
 		if (!BUF_MEM_grow_clean(buf,n+4+kn))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
 			goto err;
 			}
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
 		for (i=0; r[i] != NULL; i++)
 			{
 			s2n(nr[i],p);
 			BN_bn2bin(r[i],p);
 			p+=nr[i];
 			}
 
 #ifndef OPENSSL_NO_ECDH
 		if (type & SSL_kECDHE) 
 			{
 			/* XXX: For now, we only support named (not generic) curves.
 			 * In this situation, the serverKeyExchange message has:
 			 * [1 byte CurveType], [2 byte CurveName]
 			 * [1 byte length of encoded point], followed by
 			 * the actual encoded point itself
 			 */
 			*p = NAMED_CURVE_TYPE;
 			p += 1;
 			*p = 0;
 			p += 1;
 			*p = curve_id;
 			p += 1;
 			*p = encodedlen;
 			p += 1;
 			memcpy((unsigned char*)p, 
 			    (unsigned char *)encodedPoint, 
 			    encodedlen);
 			OPENSSL_free(encodedPoint);
 			encodedPoint = NULL;
 			p += encodedlen;
 			}
 #endif
 
 		/* not anonymous */
 		if (pkey != NULL)
 			{
 			/* n is the length of the params, they start at &(d[4])
 			 * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
 			if (pkey->type == EVP_PKEY_RSA)
 				{
 				q=md_buf;
 				j=0;
 				for (num=2; num > 0; num--)
 					{
 					EVP_MD_CTX_set_flags(&md_ctx,
 						EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 					EVP_DigestInit_ex(&md_ctx,(num == 2)
 						?s->ctx->md5:s->ctx->sha1, NULL);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 					EVP_DigestUpdate(&md_ctx,&(d[4]),n);
 					EVP_DigestFinal_ex(&md_ctx,q,
 						(unsigned int *)&i);
 					q+=i;
 					j+=i;
 					}
 				if (RSA_sign(NID_md5_sha1, md_buf, j,
 					&(p[2]), &u, pkey->pkey.rsa) <= 0)
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
 					goto err;
 					}
 				s2n(u,p);
 				n+=u+2;
 				}
 			else
 #endif
 #if !defined(OPENSSL_NO_DSA)
 				if (pkey->type == EVP_PKEY_DSA)
 				{
 				/* lets do DSS */
 				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
 				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(d[4]),n);
 				if (!EVP_SignFinal(&md_ctx,&(p[2]),
 					(unsigned int *)&i,pkey))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
 					goto err;
 					}
 				s2n(i,p);
 				n+=i+2;
 				}
 			else
 #endif
 #if !defined(OPENSSL_NO_ECDSA)
 				if (pkey->type == EVP_PKEY_EC)
 				{
 				/* let's do ECDSA */
 				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
 				EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
 				EVP_SignUpdate(&md_ctx,&(d[4]),n);
 				if (!EVP_SignFinal(&md_ctx,&(p[2]),
 					(unsigned int *)&i,pkey))
 					{
 					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
 					goto err;
 					}
 				s2n(i,p);
 				n+=i+2;
 				}
 			else
 #endif
 				{
 				/* Is this error check actually needed? */
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE);
 				goto f_err;
 				}
 			}
 
 		*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 		s->init_num=n+4;
 		s->init_off=0;
 		}
 
 	s->state = SSL3_ST_SW_KEY_EXCH_B;
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
 #ifndef OPENSSL_NO_ECDH
 	if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
 	BN_CTX_free(bn_ctx);
 #endif
 	EVP_MD_CTX_cleanup(&md_ctx);
 	return(-1);
 	}
 
 int ssl3_send_certificate_request(SSL *s)
 	{
 	unsigned char *p,*d;
 	int i,j,nl,off,n;
 	STACK_OF(X509_NAME) *sk=NULL;
 	X509_NAME *name;
 	BUF_MEM *buf;
 
 	if (s->state == SSL3_ST_SW_CERT_REQ_A)
 		{
 		buf=s->init_buf;
 
 		d=p=(unsigned char *)&(buf->data[4]);
 
 		/* get the list of acceptable cert types */
 		p++;
 		n=ssl3_get_req_cert_type(s,p);
 		d[0]=n;
 		p+=n;
 		n++;
 
 		off=n;
 		p+=2;
 		n+=2;
 
 		sk=SSL_get_client_CA_list(s);
 		nl=0;
 		if (sk != NULL)
 			{
 			for (i=0; idata[4+n]);
 				if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
 					{
 					s2n(j,p);
 					i2d_X509_NAME(name,&p);
 					n+=2+j;
 					nl+=2+j;
 					}
 				else
 					{
 					d=p;
 					i2d_X509_NAME(name,&p);
 					j-=2; s2n(j,d); j+=2;
 					n+=j;
 					nl+=j;
 					}
 				}
 			}
 		/* else no CA names */
 		p=(unsigned char *)&(buf->data[4+off]);
 		s2n(nl,p);
 
 		d=(unsigned char *)buf->data;
 		*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
 		l2n3(n,d);
 
 		/* we should now have things packed up, so lets send
 		 * it off */
 
 		s->init_num=n+4;
 		s->init_off=0;
 #ifdef NETSCAPE_HANG_BUG
 		if (!BUF_MEM_grow_clean(buf, s->init_num + 4))
 			{
 			SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
 			goto err;
 			}
 		p=(unsigned char *)s->init_buf->data + s->init_num;
 
 		/* do the header */
 		*(p++)=SSL3_MT_SERVER_DONE;
 		*(p++)=0;
 		*(p++)=0;
 		*(p++)=0;
 		s->init_num += 4;
 #endif
 
 		s->state = SSL3_ST_SW_CERT_REQ_B;
 		}
 
 	/* SSL3_ST_SW_CERT_REQ_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 err:
 	return(-1);
 	}
 
 int ssl3_get_client_key_exchange(SSL *s)
 	{
 	int i,al,ok;
 	long n;
 	unsigned long l;
 	unsigned char *p;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa=NULL;
 	EVP_PKEY *pkey=NULL;
 #endif
 #ifndef OPENSSL_NO_DH
 	BIGNUM *pub=NULL;
 	DH *dh_srvr;
 #endif
 #ifndef OPENSSL_NO_KRB5
         KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *srvr_ecdh = NULL;
 	EVP_PKEY *clnt_pub_pkey = NULL;
 	EC_POINT *clnt_ecpoint = NULL;
 	BN_CTX *bn_ctx = NULL; 
 #endif
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_KEY_EXCH_A,
 		SSL3_ST_SR_KEY_EXCH_B,
 		SSL3_MT_CLIENT_KEY_EXCHANGE,
 		2048, /* ??? */
 		&ok);
 
 	if (!ok) return((int)n);
 	p=(unsigned char *)s->init_msg;
 
 	l=s->s3->tmp.new_cipher->algorithms;
 
 #ifndef OPENSSL_NO_RSA
 	if (l & SSL_kRSA)
 		{
 		unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
 		int decrypt_len;
 		unsigned char decrypt_good, version_good;
 
 		/* FIX THIS UP EAY EAY EAY EAY */
 		if (s->s3->tmp.use_rsa_tmp)
 			{
 			if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
 				rsa=s->cert->rsa_tmp;
 			/* Don't do a callback because rsa_tmp should
 			 * be sent already */
 			if (rsa == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY);
 				goto f_err;
 
 				}
 			}
 		else
 			{
 			pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
 			if (	(pkey == NULL) ||
 				(pkey->type != EVP_PKEY_RSA) ||
 				(pkey->pkey.rsa == NULL))
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
 				goto f_err;
 				}
 			rsa=pkey->pkey.rsa;
 			}
 
 		/* TLS and [incidentally] DTLS, including pre-0.9.8f */
 		if (s->version > SSL3_VERSION &&
 		    s->client_version != DTLS1_BAD_VER)
 			{
 			n2s(p,i);
 			if (n != i+2)
 				{
 				if (!(s->options & SSL_OP_TLS_D5_BUG))
 					{
 					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
 					goto err;
 					}
 				else
 					p-=2;
 				}
 			else
 				n=i;
 			}
 
 		/* We must not leak whether a decryption failure occurs because
 		 * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see
 		 * RFC 2246, section 7.4.7.1). The code follows that advice of
 		 * the TLS RFC and generates a random premaster secret for the
 		 * case that the decrypt fails. See
 		 * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */
 
 		/* should be RAND_bytes, but we cannot work around a failure. */
 		if (RAND_pseudo_bytes(rand_premaster_secret,
 				      sizeof(rand_premaster_secret)) <= 0)
 			goto err;
 		decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
 		ERR_clear_error();
 
 		/* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
 		 * decrypt_good will be 0xff if so and zero otherwise. */
 		decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
 
 		/* If the version in the decrypted pre-master secret is correct
 		 * then version_good will be 0xff, otherwise it'll be zero.
 		 * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
 		 * (http://eprint.iacr.org/2003/052/) exploits the version
 		 * number check as a "bad version oracle". Thus version checks
 		 * are done in constant time and are treated like any other
 		 * decryption error. */
 		version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
 		version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
 
 		/* The premaster secret must contain the same version number as
 		 * the ClientHello to detect version rollback attacks
 		 * (strangely, the protocol does not offer such protection for
 		 * DH ciphersuites). However, buggy clients exist that send the
 		 * negotiated protocol version instead if the server does not
 		 * support the requested protocol version. If
 		 * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
 		if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
 			{
 			unsigned char workaround_good;
 			workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
 			workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
 			version_good |= workaround_good;
 			}
 
 		/* Both decryption and version must be good for decrypt_good
 		 * to remain non-zero (0xff). */
 		decrypt_good &= version_good;
 
 		/* Now copy rand_premaster_secret over p using
 		 * decrypt_good_mask. */
 		for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
 			{
 			p[i] = constant_time_select_8(decrypt_good, p[i],
 						      rand_premaster_secret[i]);
 			}
 
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,
 				p,i);
 		OPENSSL_cleanse(p,i);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DH
 		if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
 		{
 		n2s(p,i);
 		if (n != i+2)
 			{
 			if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
 				goto err;
 				}
 			else
 				{
 				p-=2;
 				i=(int)n;
 				}
 			}
 
 		if (n == 0L) /* the parameters are in the cert */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
 			goto f_err;
 			}
 		else
 			{
 			if (s->s3->tmp.dh == NULL)
 				{
 				al=SSL_AD_HANDSHAKE_FAILURE;
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
 				goto f_err;
 				}
 			else
 				dh_srvr=s->s3->tmp.dh;
 			}
 
 		pub=BN_bin2bn(p,i,NULL);
 		if (pub == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB);
 			goto err;
 			}
 
 		i=DH_compute_key(p,pub,dh_srvr);
 
 		if (i <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
 			BN_clear_free(pub);
 			goto err;
 			}
 
 		DH_free(s->s3->tmp.dh);
 		s->s3->tmp.dh=NULL;
 
 		BN_clear_free(pub);
 		pub=NULL;
 		s->session->master_key_length=
 			s->method->ssl3_enc->generate_master_secret(s,
 				s->session->master_key,p,i);
 		OPENSSL_cleanse(p,i);
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_KRB5
         if (l & SSL_kKRB5)
                 {
                 krb5_error_code		krb5rc;
 		krb5_data		enc_ticket;
 		krb5_data		authenticator;
 		krb5_data		enc_pms;
                 KSSL_CTX		*kssl_ctx = s->kssl_ctx;
 		EVP_CIPHER_CTX		ciph_ctx;
 		EVP_CIPHER		*enc = NULL;
 		unsigned char		iv[EVP_MAX_IV_LENGTH];
 		unsigned char		pms[SSL_MAX_MASTER_KEY_LENGTH
                                                + EVP_MAX_BLOCK_LENGTH];
 		int                     padl, outl;
 		krb5_timestamp		authtime = 0;
 		krb5_ticket_times	ttimes;
+        int kerr = 0;
 
 		EVP_CIPHER_CTX_init(&ciph_ctx);
 
                 if (!kssl_ctx)  kssl_ctx = kssl_ctx_new();
 
 		n2s(p,i);
 		enc_ticket.length = i;
 
 		if (n < (int)enc_ticket.length + 6)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		enc_ticket.data = (char *)p;
 		p+=enc_ticket.length;
 
 		n2s(p,i);
 		authenticator.length = i;
 
 		if (n < (int)(enc_ticket.length + authenticator.length) + 6)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		authenticator.data = (char *)p;
 		p+=authenticator.length;
 
 		n2s(p,i);
 		enc_pms.length = i;
 		enc_pms.data = (char *)p;
 		p+=enc_pms.length;
 
 		/* Note that the length is checked again below,
 		** after decryption
 		*/
 		if(enc_pms.length > sizeof pms)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
 		if (n != (long)(enc_ticket.length + authenticator.length +
 						enc_pms.length + 6))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
 			goto err;
 			}
 
                 if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
 					&kssl_err)) != 0)
                         {
 #ifdef KSSL_DEBUG
                         printf("kssl_sget_tkt rtn %d [%d]\n",
                                 krb5rc, kssl_err.reason);
                         if (kssl_err.text)
                                 printf("kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                                 kssl_err.reason);
                         goto err;
                         }
 
 		/*  Note: no authenticator is not considered an error,
 		**  but will return authtime == 0.
 		*/
 		if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
 					&authtime, &kssl_err)) != 0)
 			{
 #ifdef KSSL_DEBUG
                         printf("kssl_check_authent rtn %d [%d]\n",
                                 krb5rc, kssl_err.reason);
                         if (kssl_err.text)
                                 printf("kssl_err text= %s\n", kssl_err.text);
 #endif	/* KSSL_DEBUG */
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                                 kssl_err.reason);
                         goto err;
 			}
 
 		if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
                         goto err;
 			}
 
 #ifdef KSSL_DEBUG
                 kssl_ctx_show(kssl_ctx);
 #endif	/* KSSL_DEBUG */
 
 		enc = kssl_map_enc(kssl_ctx->enctype);
                 if (enc == NULL)
                     goto err;
 
 		memset(iv, 0, sizeof iv);	/* per RFC 1510 */
 
 		if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
 			goto err;
 			}
 		if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
 					(unsigned char *)enc_pms.data, enc_pms.length))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		outl += padl;
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
 		    {
 		    /* The premaster secret must contain the same version number as the
 		     * ClientHello to detect version rollback attacks (strangely, the
 		     * protocol does not offer such protection for DH ciphersuites).
 		     * However, buggy clients exist that send random bytes instead of
 		     * the protocol version.
 		     * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. 
 		     * (Perhaps we should have a separate BUG value for the Kerberos cipher)
 		     */
 		    if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
 		        {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_AD_DECODE_ERROR);
-			goto err;
+                kerr = 1;
+                goto kclean;
 			}
 		    }
 
 		EVP_CIPHER_CTX_cleanup(&ciph_ctx);
 
                 s->session->master_key_length=
                         s->method->ssl3_enc->generate_master_secret(s,
                                 s->session->master_key, pms, outl);
 
                 if (kssl_ctx->client_princ)
                         {
                         size_t len = strlen(kssl_ctx->client_princ);
                         if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) 
                                 {
                                 s->session->krb5_client_princ_len = len;
                                 memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
                                 }
                         }
 
 
                 /*  Was doing kssl_ctx_free() here,
 		**  but it caused problems for apache.
                 **  kssl_ctx = kssl_ctx_free(kssl_ctx);
                 **  if (s->kssl_ctx)  s->kssl_ctx = NULL;
                 */
-                }
-	else
+
+ kclean:
+        OPENSSL_cleanse(pms, sizeof(pms));
+        if (kerr)
+            goto err;
+    } else
 #endif	/* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
 		if ((l & SSL_kECDH) || (l & SSL_kECDHE))
 		{
 		int ret = 1;
 		int field_size = 0;
 		const EC_KEY   *tkey;
 		const EC_GROUP *group;
 		const BIGNUM *priv_key;
 
                 /* initialize structures for server's ECDH key pair */
 		if ((srvr_ecdh = EC_KEY_new()) == NULL) 
 			{
                 	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
                 	goto err;
 			}
 
 		/* Let's get server private key and group information */
 		if (l & SSL_kECDH) 
 			{ 
                         /* use the certificate */
 			tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
 			}
 		else
 			{
 			/* use the ephermeral values we saved when
 			 * generating the ServerKeyExchange msg.
 			 */
 			tkey = s->s3->tmp.ecdh;
 			}
 
 		group    = EC_KEY_get0_group(tkey);
 		priv_key = EC_KEY_get0_private_key(tkey);
 
 		if (!EC_KEY_set_group(srvr_ecdh, group) ||
 		    !EC_KEY_set_private_key(srvr_ecdh, priv_key))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       ERR_R_EC_LIB);
 			goto err;
 			}
 
 		/* Let's get client's public key */
 		if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 
                 if (n == 0L) 
                         {
 			/* Client Publickey was in Client Certificate */
 
 			 if (l & SSL_kECDHE) 
 				 {
 				 al=SSL_AD_HANDSHAKE_FAILURE;
 				 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
 				 goto f_err;
 				 }
                         if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
 			    == NULL) || 
 			    (clnt_pub_pkey->type != EVP_PKEY_EC))
                         	{
 				/* XXX: For now, we do not support client
 				 * authentication using ECDH certificates
 				 * so this branch (n == 0L) of the code is
 				 * never executed. When that support is
 				 * added, we ought to ensure the key 
 				 * received in the certificate is 
 				 * authorized for key agreement.
 				 * ECDH_compute_key implicitly checks that
 				 * the two ECDH shares are for the same
 				 * group.
 				 */
                            	al=SSL_AD_HANDSHAKE_FAILURE;
                            	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
                            	goto f_err;
                            	}
 
 			if (EC_POINT_copy(clnt_ecpoint,
 			    EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 					ERR_R_EC_LIB);
 				goto err;
 				}
                         ret = 2; /* Skip certificate verify processing */
                         }
                 else
                         {
 			/* Get client's public key from encoded point
 			 * in the ClientKeyExchange message.
 			 */
 			if ((bn_ctx = BN_CTX_new()) == NULL)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_MALLOC_FAILURE);
 				goto err;
 				}
 
                         /* Get encoded point length */
                         i = *p; 
 			p += 1;
 			if (n != 1 + i)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
                         if (EC_POINT_oct2point(group, 
 			    clnt_ecpoint, p, i, bn_ctx) == 0)
 				{
 				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				    ERR_R_EC_LIB);
 				goto err;
 				}
                         /* p is pointing to somewhere in the buffer
                          * currently, so set it to the start 
                          */ 
                         p=(unsigned char *)s->init_buf->data;
                         }
 
 		/* Compute the shared pre-master secret */
 		field_size = EC_GROUP_get_degree(group);
 		if (field_size <= 0)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, 
 			       ERR_R_ECDH_LIB);
 			goto err;
 			}
 		i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
                 if (i <= 0)
                         {
                         SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			    ERR_R_ECDH_LIB);
                         goto err;
                         }
 
 		EVP_PKEY_free(clnt_pub_pkey);
 		EC_POINT_free(clnt_ecpoint);
 		if (srvr_ecdh != NULL) 
 			EC_KEY_free(srvr_ecdh);
 		BN_CTX_free(bn_ctx);
 
 		/* Compute the master secret */
                 s->session->master_key_length = s->method->ssl3_enc-> \
 		    generate_master_secret(s, s->session->master_key, p, i);
 		
                 OPENSSL_cleanse(p, i);
                 return (ret);
 		}
 	else
 #endif
 		{
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_UNKNOWN_CIPHER_TYPE);
 		goto f_err;
 		}
 
 	return(1);
 f_err:
 	ssl3_send_alert(s,SSL3_AL_FATAL,al);
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
 err:
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EVP_PKEY_free(clnt_pub_pkey);
 	EC_POINT_free(clnt_ecpoint);
 	if (srvr_ecdh != NULL) 
 		EC_KEY_free(srvr_ecdh);
 	BN_CTX_free(bn_ctx);
 #endif
 	return(-1);
 	}
 
 int ssl3_get_cert_verify(SSL *s)
 	{
 	EVP_PKEY *pkey=NULL;
 	unsigned char *p;
 	int al,ok,ret=0;
 	long n;
 	int type=0,i,j;
 	X509 *peer;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_VRFY_A,
 		SSL3_ST_SR_CERT_VRFY_B,
 		-1,
 		SSL3_RT_MAX_PLAIN_LENGTH,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if (s->session->peer != NULL)
 		{
 		peer=s->session->peer;
 		pkey=X509_get_pubkey(peer);
 		type=X509_certificate_type(peer,pkey);
 		}
 	else
 		{
 		peer=NULL;
 		pkey=NULL;
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
 		{
 		s->s3->tmp.reuse_message=1;
 		if (peer != NULL)
 			{
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
 			goto f_err;
 			}
 		ret=1;
 		goto end;
 		}
 
 	if (peer == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	if (!(type & EVP_PKT_SIGN))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
 		al=SSL_AD_ILLEGAL_PARAMETER;
 		goto f_err;
 		}
 
 	if (s->s3->change_cipher_spec)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		goto f_err;
 		}
 
 	/* we now have a signature that we need to verify */
 	p=(unsigned char *)s->init_msg;
 	n2s(p,i);
 	n-=2;
 	if (i > n)
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
 		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
 	j=EVP_PKEY_size(pkey);
 	if ((i > j) || (n > j) || (n <= 0))
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
 		al=SSL_AD_DECODE_ERROR;
 		goto f_err;
 		}
 
 #ifndef OPENSSL_NO_RSA 
 	if (pkey->type == EVP_PKEY_RSA)
 		{
 		i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
 			MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, 
 							pkey->pkey.rsa);
 		if (i < 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
 			goto f_err;
 			}
 		if (i == 0)
 			{
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_DSA
 		if (pkey->type == EVP_PKEY_DSA)
 		{
 		j=DSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 #ifndef OPENSSL_NO_ECDSA
 		if (pkey->type == EVP_PKEY_EC)
 		{
 		j=ECDSA_verify(pkey->save_type,
 			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
 			SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec);
 		if (j <= 0)
 			{
 			/* bad signature */
 			al=SSL_AD_DECRYPT_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
 			    SSL_R_BAD_ECDSA_SIGNATURE);
 			goto f_err;
 			}
 		}
 	else
 #endif
 		{
 		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
 		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
 		goto f_err;
 		}
 
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 end:
 	EVP_PKEY_free(pkey);
 	return(ret);
 	}
 
 int ssl3_get_client_certificate(SSL *s)
 	{
 	int i,ok,al,ret= -1;
 	X509 *x=NULL;
 	unsigned long l,nc,llen,n;
 	const unsigned char *p,*q;
 	unsigned char *d;
 	STACK_OF(X509) *sk=NULL;
 
 	n=s->method->ssl_get_message(s,
 		SSL3_ST_SR_CERT_A,
 		SSL3_ST_SR_CERT_B,
 		-1,
 		s->max_cert_list,
 		&ok);
 
 	if (!ok) return((int)n);
 
 	if	(s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
 		{
 		if (	(s->verify_mode & SSL_VERIFY_PEER) &&
 			(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		/* If tls asked for a client cert, the client must return a 0 list */
 		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
 			al=SSL_AD_UNEXPECTED_MESSAGE;
 			goto f_err;
 			}
 		s->s3->tmp.reuse_message=1;
 		return(1);
 		}
 
 	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
 		{
 		al=SSL_AD_UNEXPECTED_MESSAGE;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
 		goto f_err;
 		}
 	p=d=(unsigned char *)s->init_msg;
 
 	if ((sk=sk_X509_new_null()) == NULL)
 		{
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 		goto err;
 		}
 
 	n2l3(p,llen);
 	if (llen+3 != n)
 		{
 		al=SSL_AD_DECODE_ERROR;
 		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
 		goto f_err;
 		}
 	for (nc=0; nc llen)
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 
 		q=p;
 		x=d2i_X509(NULL,&p,l);
 		if (x == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
 			goto err;
 			}
 		if (p != (q+l))
 			{
 			al=SSL_AD_DECODE_ERROR;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
 			goto f_err;
 			}
 		if (!sk_X509_push(sk,x))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		x=NULL;
 		nc+=l+3;
 		}
 
 	if (sk_X509_num(sk) <= 0)
 		{
 		/* TLS does not mind 0 certs returned */
 		if (s->version == SSL3_VERSION)
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
 			goto f_err;
 			}
 		/* Fail for TLS only if we required a certificate */
 		else if ((s->verify_mode & SSL_VERIFY_PEER) &&
 			 (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			goto f_err;
 			}
 		}
 	else
 		{
 		i=ssl_verify_cert_chain(s,sk);
 		if (i <= 0)
 			{
 			al=ssl_verify_alarm_type(s->verify_result);
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
 			goto f_err;
 			}
 		}
 
 	if (s->session->peer != NULL) /* This should not be needed */
 		X509_free(s->session->peer);
 	s->session->peer=sk_X509_shift(sk);
 	s->session->verify_result = s->verify_result;
 
 	/* With the current implementation, sess_cert will always be NULL
 	 * when we arrive here. */
 	if (s->session->sess_cert == NULL)
 		{
 		s->session->sess_cert = ssl_sess_cert_new();
 		if (s->session->sess_cert == NULL)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
 			goto err;
 			}
 		}
 	if (s->session->sess_cert->cert_chain != NULL)
 		sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
 	s->session->sess_cert->cert_chain=sk;
 	/* Inconsistency alert: cert_chain does *not* include the
 	 * peer's own certificate, while we do include it in s3_clnt.c */
 
 	sk=NULL;
 
 	ret=1;
 	if (0)
 		{
 f_err:
 		ssl3_send_alert(s,SSL3_AL_FATAL,al);
 		}
 err:
 	if (x != NULL) X509_free(x);
 	if (sk != NULL) sk_X509_pop_free(sk,X509_free);
 	return(ret);
 	}
 
 int ssl3_send_server_certificate(SSL *s)
 	{
 	unsigned long l;
 	X509 *x;
 
 	if (s->state == SSL3_ST_SW_CERT_A)
 		{
 		x=ssl_get_server_send_cert(s);
 		if (x == NULL &&
                         /* VRS: allow null cert if auth == KRB5 */
                         (s->s3->tmp.new_cipher->algorithms
                                 & (SSL_MKEY_MASK|SSL_AUTH_MASK))
                         != (SSL_aKRB5|SSL_kKRB5))
 			{
 			SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
 			return(0);
 			}
 
 		l=ssl3_output_cert_chain(s,x);
 		s->state=SSL3_ST_SW_CERT_B;
 		s->init_num=(int)l;
 		s->init_off=0;
 		}
 
 	/* SSL3_ST_SW_CERT_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 
 #ifndef OPENSSL_NO_ECDH
 /* This is the complement of curve_id2nid in s3_clnt.c. */
 static int nid2curve_id(int nid)
 {
 	/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
 	 * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
 	switch (nid) {
 	case NID_sect163k1: /* sect163k1 (1) */
 		return 1;
 	case NID_sect163r1: /* sect163r1 (2) */
 		return 2;
 	case NID_sect163r2: /* sect163r2 (3) */
 		return 3;
 	case NID_sect193r1: /* sect193r1 (4) */ 
 		return 4;
 	case NID_sect193r2: /* sect193r2 (5) */ 
 		return 5;
 	case NID_sect233k1: /* sect233k1 (6) */
 		return 6;
 	case NID_sect233r1: /* sect233r1 (7) */ 
 		return 7;
 	case NID_sect239k1: /* sect239k1 (8) */ 
 		return 8;
 	case NID_sect283k1: /* sect283k1 (9) */
 		return 9;
 	case NID_sect283r1: /* sect283r1 (10) */ 
 		return 10;
 	case NID_sect409k1: /* sect409k1 (11) */ 
 		return 11;
 	case NID_sect409r1: /* sect409r1 (12) */
 		return 12;
 	case NID_sect571k1: /* sect571k1 (13) */ 
 		return 13;
 	case NID_sect571r1: /* sect571r1 (14) */ 
 		return 14;
 	case NID_secp160k1: /* secp160k1 (15) */
 		return 15;
 	case NID_secp160r1: /* secp160r1 (16) */ 
 		return 16;
 	case NID_secp160r2: /* secp160r2 (17) */ 
 		return 17;
 	case NID_secp192k1: /* secp192k1 (18) */
 		return 18;
 	case NID_X9_62_prime192v1: /* secp192r1 (19) */ 
 		return 19;
 	case NID_secp224k1: /* secp224k1 (20) */ 
 		return 20;
 	case NID_secp224r1: /* secp224r1 (21) */
 		return 21;
 	case NID_secp256k1: /* secp256k1 (22) */ 
 		return 22;
 	case NID_X9_62_prime256v1: /* secp256r1 (23) */ 
 		return 23;
 	case NID_secp384r1: /* secp384r1 (24) */
 		return 24;
 	case NID_secp521r1:  /* secp521r1 (25) */	
 		return 25;
 	default:
 		return 0;
 	}
 }
 #endif
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_send_newsession_ticket(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
 		{
 		unsigned char *p, *senc, *macstart;
 		int len, slen;
 		unsigned int hlen;
 		EVP_CIPHER_CTX ctx;
 		HMAC_CTX hctx;
 		SSL_CTX *tctx = s->initial_ctx;
 		unsigned char iv[EVP_MAX_IV_LENGTH];
 		unsigned char key_name[16];
 
 		/* get session encoding length */
 		slen = i2d_SSL_SESSION(s->session, NULL);
 		/* Some length values are 16 bits, so forget it if session is
  		 * too long
  		 */
 		if (slen > 0xFF00)
 			return -1;
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (size of message name) + 3 (message length
  		 * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
  		 * 16 (key name) + max_iv_len (iv length) +
  		 * session_length + max_enc_block_size (max encrypted session
  		 * length) + max_md_size (HMAC).
  		 */
 		if (!BUF_MEM_grow(s->init_buf,
 			26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
 			EVP_MAX_MD_SIZE + slen))
 			return -1;
 		senc = OPENSSL_malloc(slen);
 		if (!senc)
 			return -1;
 		p = senc;
 		i2d_SSL_SESSION(s->session, &p);
 
 		p=(unsigned char *)s->init_buf->data;
 		/* do the header */
 		*(p++)=SSL3_MT_NEWSESSION_TICKET;
 		/* Skip message length for now */
 		p += 3;
 		EVP_CIPHER_CTX_init(&ctx);
 		HMAC_CTX_init(&hctx);
 		/* Initialize HMAC and cipher contexts. If callback present
 		 * it does all the work otherwise use generated values
 		 * from parent ctx.
 		 */
 		if (tctx->tlsext_ticket_key_cb)
 			{
 			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
 							 &hctx, 1) < 0)
 				{
 				OPENSSL_free(senc);
 				return -1;
 				}
 			}
 		else
 			{
 			RAND_pseudo_bytes(iv, 16);
 			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
 					tctx->tlsext_tick_aes_key, iv);
 			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
 					tlsext_tick_md(), NULL);
 			memcpy(key_name, tctx->tlsext_tick_key_name, 16);
 			}
 		l2n(s->session->tlsext_tick_lifetime_hint, p);
 		/* Skip ticket length for now */
 		p += 2;
 		/* Output key name */
 		macstart = p;
 		memcpy(p, key_name, 16);
 		p += 16;
 		/* output IV */
 		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
 		p += EVP_CIPHER_CTX_iv_length(&ctx);
 		/* Encrypt session data */
 		EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
 		p += len;
 		EVP_EncryptFinal(&ctx, p, &len);
 		p += len;
 		EVP_CIPHER_CTX_cleanup(&ctx);
 
 		HMAC_Update(&hctx, macstart, p - macstart);
 		HMAC_Final(&hctx, p, &hlen);
 		HMAC_CTX_cleanup(&hctx);
 
 		p += hlen;
 		/* Now write out lengths: p points to end of data written */
 		/* Total length */
 		len = p - (unsigned char *)s->init_buf->data;
 		p=(unsigned char *)s->init_buf->data + 1;
 		l2n3(len - 4, p); /* Message length */
 		p += 4;
 		s2n(len - 10, p);  /* Ticket length */
 
 		/* number of bytes to write */
 		s->init_num= len;
 		s->state=SSL3_ST_SW_SESSION_TICKET_B;
 		s->init_off=0;
 		OPENSSL_free(senc);
 		}
 
 	/* SSL3_ST_SW_SESSION_TICKET_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 
 int ssl3_send_cert_status(SSL *s)
 	{
 	if (s->state == SSL3_ST_SW_CERT_STATUS_A)
 		{
 		unsigned char *p;
 		/* Grow buffer if need be: the length calculation is as
  		 * follows 1 (message type) + 3 (message length) +
  		 * 1 (ocsp response type) + 3 (ocsp response length)
  		 * + (ocsp response)
  		 */
 		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
 			return -1;
 
 		p=(unsigned char *)s->init_buf->data;
 
 		/* do the header */
 		*(p++)=SSL3_MT_CERTIFICATE_STATUS;
 		/* message length */
 		l2n3(s->tlsext_ocsp_resplen + 4, p);
 		/* status type */
 		*(p++)= s->tlsext_status_type;
 		/* length of OCSP response */
 		l2n3(s->tlsext_ocsp_resplen, p);
 		/* actual response */
 		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
 		/* number of bytes to write */
 		s->init_num = 8 + s->tlsext_ocsp_resplen;
 		s->state=SSL3_ST_SW_CERT_STATUS_B;
 		s->init_off = 0;
 		}
 
 	/* SSL3_ST_SW_CERT_STATUS_B */
 	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 	}
 #endif
Index: releng/9.3/crypto/openssl/ssl/ssl.h
===================================================================
--- releng/9.3/crypto/openssl/ssl/ssl.h	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/ssl.h	(revision 284295)
@@ -1,2149 +1,2150 @@
 /* ssl/ssl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #ifndef HEADER_SSL_H 
 #define HEADER_SSL_H 
 
 #include 
 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #ifndef OPENSSL_NO_BIO
 #include 
 #endif
 #ifndef OPENSSL_NO_DEPRECATED
 #ifndef OPENSSL_NO_X509
 #include 
 #endif
 #include 
 #include 
 #include 
 #endif
 #include 
 #include 
 
 #include 
 #include 
 #include 
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* SSLeay version number for ASN.1 encoding of the session information */
 /* Version 0 - initial version
  * Version 1 - added the optional peer certificate
  */
 #define SSL_SESSION_ASN1_VERSION 0x0001
 
 /* text strings for the ciphers */
 #define SSL_TXT_NULL_WITH_MD5		SSL2_TXT_NULL_WITH_MD5			
 #define SSL_TXT_RC4_128_WITH_MD5	SSL2_TXT_RC4_128_WITH_MD5		
 #define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5	
 #define SSL_TXT_RC2_128_CBC_WITH_MD5	SSL2_TXT_RC2_128_CBC_WITH_MD5		
 #define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5	
 #define SSL_TXT_IDEA_128_CBC_WITH_MD5	SSL2_TXT_IDEA_128_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_MD5	SSL2_TXT_DES_64_CBC_WITH_MD5		
 #define SSL_TXT_DES_64_CBC_WITH_SHA	SSL2_TXT_DES_64_CBC_WITH_SHA		
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5	
 #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA	
 
 /*    VRS Additional Kerberos5 entries
  */
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA
 #define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5       
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5       
 #define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5
 #define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA 
 #define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5 
 #define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5
 
 #define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA
 #define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5
 #define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA
 #define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5
 #define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
 #define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
 #define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256
 
 #define SSL_MAX_SSL_SESSION_ID_LENGTH		32
 #define SSL_MAX_SID_CTX_LENGTH			32
 
 #define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES	(512/8)
 #define SSL_MAX_KEY_ARG_LENGTH			8
 #define SSL_MAX_MASTER_KEY_LENGTH		48
 
 /* These are used to specify which ciphers to use and not to use */
 #define SSL_TXT_LOW		"LOW"
 #define SSL_TXT_MEDIUM		"MEDIUM"
 #define SSL_TXT_HIGH		"HIGH"
 #define SSL_TXT_FIPS		"FIPS"
 #define SSL_TXT_kFZA		"kFZA"
 #define	SSL_TXT_aFZA		"aFZA"
 #define SSL_TXT_eFZA		"eFZA"
 #define SSL_TXT_FZA		"FZA"
 
 #define	SSL_TXT_aNULL		"aNULL"
 #define	SSL_TXT_eNULL		"eNULL"
 #define	SSL_TXT_NULL		"NULL"
 
 #define SSL_TXT_kKRB5     	"kKRB5"
 #define SSL_TXT_aKRB5     	"aKRB5"
 #define SSL_TXT_KRB5      	"KRB5"
 
 #define SSL_TXT_kRSA		"kRSA"
 #define SSL_TXT_kDHr		"kDHr"
 #define SSL_TXT_kDHd		"kDHd"
 #define SSL_TXT_kEDH		"kEDH"
 #define	SSL_TXT_aRSA		"aRSA"
 #define	SSL_TXT_aDSS		"aDSS"
 #define	SSL_TXT_aDH		"aDH"
 #define	SSL_TXT_DSS		"DSS"
 #define SSL_TXT_DH		"DH"
 #define SSL_TXT_EDH		"EDH"
 #define SSL_TXT_ADH		"ADH"
 #define SSL_TXT_RSA		"RSA"
 #define SSL_TXT_DES		"DES"
 #define SSL_TXT_3DES		"3DES"
 #define SSL_TXT_RC4		"RC4"
 #define SSL_TXT_RC2		"RC2"
 #define SSL_TXT_IDEA		"IDEA"
 #define SSL_TXT_SEED		"SEED"
 #define SSL_TXT_AES		"AES"
 #define SSL_TXT_CAMELLIA	"CAMELLIA"
 #define SSL_TXT_MD5		"MD5"
 #define SSL_TXT_SHA1		"SHA1"
 #define SSL_TXT_SHA		"SHA"
 #define SSL_TXT_EXP		"EXP"
 #define SSL_TXT_EXPORT		"EXPORT"
 #define SSL_TXT_EXP40		"EXPORT40"
 #define SSL_TXT_EXP56		"EXPORT56"
 #define SSL_TXT_SSLV2		"SSLv2"
 #define SSL_TXT_SSLV3		"SSLv3"
 #define SSL_TXT_TLSV1		"TLSv1"
 #define SSL_TXT_ALL		"ALL"
 #define SSL_TXT_ECC		"ECCdraft" /* ECC ciphersuites are not yet official */
 
 /*
  * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
  * ciphers normally not being used.
  * Example: "RC4" will activate all ciphers using RC4 including ciphers
  * without authentication, which would normally disabled by DEFAULT (due
  * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
  * will make sure that it is also disabled in the specific selection.
  * COMPLEMENTOF* identifiers are portable between version, as adjustments
  * to the default cipher setup will also be included here.
  *
  * COMPLEMENTOFDEFAULT does not experience the same special treatment that
  * DEFAULT gets, as only selection is being done and no sorting as needed
  * for DEFAULT.
  */
 #define SSL_TXT_CMPALL		"COMPLEMENTOFALL"
 #define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT"
 
 /* The following cipher list is used by default.
  * It also is substituted when an application-defined cipher list string
  * starts with 'DEFAULT'. */
 #define SSL_DEFAULT_CIPHER_LIST	"AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" /* low priority for RC4 */
 
 /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
 #define SSL_SENT_SHUTDOWN	1
 #define SSL_RECEIVED_SHUTDOWN	2
 
 #ifdef __cplusplus
 }
 #endif
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 #if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
 #define OPENSSL_NO_SSL2
 #endif
 
 #define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1
 #define SSL_FILETYPE_PEM	X509_FILETYPE_PEM
 
 /* This is needed to stop compilers complaining about the
  * 'struct ssl_st *' function parameters used to prototype callbacks
  * in SSL_CTX. */
 typedef struct ssl_st *ssl_crock_st;
 
 /* used to hold info on the particular ciphers used */
 typedef struct ssl_cipher_st
 	{
 	int valid;
 	const char *name;		/* text name */
 	unsigned long id;		/* id, 4 bytes, first is version */
 	unsigned long algorithms;	/* what ciphers are used */
 	unsigned long algo_strength;	/* strength and export flags */
 	unsigned long algorithm2;	/* Extra flags */
 	int strength_bits;		/* Number of bits really used */
 	int alg_bits;			/* Number of bits for algorithm */
 	unsigned long mask;		/* used for matching */
 	unsigned long mask_strength;	/* also used for matching */
 	} SSL_CIPHER;
 
 DECLARE_STACK_OF(SSL_CIPHER)
 
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 typedef struct ssl_method_st
 	{
 	int version;
 	int (*ssl_new)(SSL *s);
 	void (*ssl_clear)(SSL *s);
 	void (*ssl_free)(SSL *s);
 	int (*ssl_accept)(SSL *s);
 	int (*ssl_connect)(SSL *s);
 	int (*ssl_read)(SSL *s,void *buf,int len);
 	int (*ssl_peek)(SSL *s,void *buf,int len);
 	int (*ssl_write)(SSL *s,const void *buf,int len);
 	int (*ssl_shutdown)(SSL *s);
 	int (*ssl_renegotiate)(SSL *s);
 	int (*ssl_renegotiate_check)(SSL *s);
 	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
 		max, int *ok);
 	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, 
 		int peek);
 	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
 	int (*ssl_dispatch_alert)(SSL *s);
 	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
 	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
 	SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
 	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
 	int (*ssl_pending)(const SSL *s);
 	int (*num_ciphers)(void);
 	SSL_CIPHER *(*get_cipher)(unsigned ncipher);
 	struct ssl_method_st *(*get_ssl_method)(int version);
 	long (*get_timeout)(void);
 	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
 	int (*ssl_version)(void);
 	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
 	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
 	} SSL_METHOD;
 
 /* Lets make this into an ASN.1 type structure as follows
  * SSL_SESSION_ID ::= SEQUENCE {
  *	version 		INTEGER,	-- structure version number
  *	SSLversion 		INTEGER,	-- SSL version number
  *	Cipher 			OCTET_STRING,	-- the 3 byte cipher ID
  *	Session_ID 		OCTET_STRING,	-- the Session ID
  *	Master_key 		OCTET_STRING,	-- the master key
  *	KRB5_principal		OCTET_STRING	-- optional Kerberos principal
  *	Key_Arg [ 0 ] IMPLICIT	OCTET_STRING,	-- the optional Key argument
  *	Time [ 1 ] EXPLICIT	INTEGER,	-- optional Start Time
  *	Timeout [ 2 ] EXPLICIT	INTEGER,	-- optional Timeout ins seconds
  *	Peer [ 3 ] EXPLICIT	X509,		-- optional Peer Certificate
  *	Session_ID_context [ 4 ] EXPLICIT OCTET_STRING,   -- the Session ID context
  *	Verify_result [ 5 ] EXPLICIT INTEGER    -- X509_V_... code for `Peer'
  *	Compression [6] IMPLICIT ASN1_OBJECT	-- compression OID XXXXX
  *	}
  * Look in ssl/ssl_asn1.c for more details
  * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
  */
 typedef struct ssl_session_st
 	{
 	int ssl_version;	/* what ssl version session info is
 				 * being kept in here? */
 
 	/* only really used in SSLv2 */
 	unsigned int key_arg_length;
 	unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
 	int master_key_length;
 	unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
 	/* session_id - valid? */
 	unsigned int session_id_length;
 	unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
 	/* this is used to determine whether the session is being reused in
 	 * the appropriate context. It is up to the application to set this,
 	 * via SSL_new */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 #ifndef OPENSSL_NO_KRB5
         unsigned int krb5_client_princ_len;
         unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
 #endif /* OPENSSL_NO_KRB5 */
 
 	int not_resumable;
 
 	/* The cert is the certificate used to establish this connection */
 	struct sess_cert_st /* SESS_CERT */ *sess_cert;
 
 	/* This is the cert for the other end.
 	 * On clients, it will be the same as sess_cert->peer_key->x509
 	 * (the latter is not enough as sess_cert is not retained
 	 * in the external representation of sessions, see ssl_asn1.c). */
 	X509 *peer;
 	/* when app_verify_callback accepts a session where the peer's certificate
 	 * is not ok, we must remember the error for session reuse: */
 	long verify_result; /* only for servers */
 
 	int references;
 	long timeout;
 	long time;
 
 	int compress_meth;		/* Need to lookup the method */
 
 	SSL_CIPHER *cipher;
 	unsigned long cipher_id;	/* when ASN.1 loaded, this
 					 * needs to be used to load
 					 * the 'cipher' structure */
 
 	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
 
 	CRYPTO_EX_DATA ex_data; /* application specific data */
 
 	/* These are used to make removal of session-ids more
 	 * efficient and to implement a maximum cache size. */
 	struct ssl_session_st *prev,*next;
 #ifndef OPENSSL_NO_TLSEXT
 	char *tlsext_hostname;
 	/* RFC4507 info */
 	unsigned char *tlsext_tick;	/* Session ticket */
 	size_t	tlsext_ticklen;		/* Session ticket length */	
 	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */
 #endif
 	} SSL_SESSION;
 
 
 #define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L
 #define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L
 /* Allow initial connection to servers that don't support RI */
 #define SSL_OP_LEGACY_SERVER_CONNECT			0x00000004L
 #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG		0x00000008L
 #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG		0x00000010L
 #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER		0x00000020L
 #define SSL_OP_SAFARI_ECDHE_ECDSA_BUG			0x00000040L
 #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L
 #define SSL_OP_TLS_D5_BUG				0x00000100L
 #define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L
 
 /* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */
 #define SSL_OP_MSIE_SSLV2_RSA_PADDING			0x0
 
 /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
  * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
  * the workaround is not needed.  Unfortunately some broken SSL/TLS
  * implementations cannot handle it at all, which is why we include
  * it in SSL_OP_ALL. */
 #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */
 
 /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
  *             This used to be 0x000FFFFFL before 0.9.7. */
 #define SSL_OP_ALL					0x00000FFFL
 
 /* DTLS options */
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
 /* Turn on Cookie Exchange (on relevant for servers) */
 #define SSL_OP_COOKIE_EXCHANGE              0x00002000L
 /* Don't use RFC4507 ticket extension */
 #define SSL_OP_NO_TICKET	            0x00004000L
 /* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */
 #define SSL_OP_CISCO_ANYCONNECT		    0x00008000L
 
 /* As server, disallow session resumption on renegotiation */
 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L
 /* Permit unsafe legacy renegotiation */
 #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L
 /* If set, always create a new key when using tmp_ecdh parameters */
 #define SSL_OP_SINGLE_ECDH_USE				0x00080000L
 /* If set, always create a new key when using tmp_dh parameters */
 #define SSL_OP_SINGLE_DH_USE				0x00100000L
 /* Does nothing: retained for compatibiity */
 #define SSL_OP_EPHEMERAL_RSA				0x0
 /* Set on servers to choose the cipher according to the server's
  * preferences */
 #define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L
 /* If set, a server will allow a client to issue a SSLv3.0 version number
  * as latest version supported in the premaster secret, even when TLSv1.0
  * (version 3.1) was announced in the client hello. Normally this is
  * forbidden to prevent version rollback attacks. */
 #define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L
 
 #define SSL_OP_NO_SSLv2					0x01000000L
 #define SSL_OP_NO_SSLv3					0x02000000L
 #define SSL_OP_NO_TLSv1					0x04000000L
 
 /* The next flag deliberately changes the ciphertest, this is a check
  * for the PKCS#1 attack */
 #define SSL_OP_PKCS1_CHECK_1				0x08000000L
 #define SSL_OP_PKCS1_CHECK_2				0x10000000L
 #define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L
 
 
 /* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
  * when just a single record has been written): */
 #define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
 /* Make it possible to retry SSL_write() with changed buffer location
  * (buffer contents must stay the same!); this is not the default to avoid
  * the misconception that non-blocking SSL_write() behaves like
  * non-blocking write(): */
 #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
 /* Never bother the application with retries if the transport
  * is blocking: */
 #define SSL_MODE_AUTO_RETRY 0x00000004L
 /* Don't attempt to automatically build certificate chain */
 #define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
 /* Send TLS_FALLBACK_SCSV in the ClientHello.
  * To be set only by applications that reconnect with a downgraded protocol
  * version; see draft-ietf-tls-downgrade-scsv-00 for details.
  *
  * DO NOT ENABLE THIS if your application attempts a normal handshake.
  * Only use this in explicit fallback retries, following the guidance
  * in draft-ietf-tls-downgrade-scsv-00.
  */
 #define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L
 
 
 /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
  * they cannot be used to clear bits. */
 
 #define SSL_CTX_set_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_CTX_clear_options(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_CTX_get_options(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
 #define SSL_set_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
 #define SSL_clear_options(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
 #define SSL_get_options(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
 
 #define SSL_CTX_set_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
 #define SSL_CTX_clear_mode(ctx,op) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_CTX_get_mode(ctx) \
 	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
 #define SSL_clear_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
 #define SSL_set_mode(ssl,op) \
 	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
 #define SSL_get_mode(ssl) \
         SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
 #define SSL_set_mtu(ssl, mtu) \
         SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
 
 #define SSL_get_secure_renegotiation_support(ssl) \
 	SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
 
 void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
 #define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 #define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
 
 
 
 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
 #else
 #define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
 #endif
 
 #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20)
 
 /* This callback type is used inside SSL_CTX, SSL, and in the functions that set
  * them. It is used to override the generation of SSL/TLS session IDs in a
  * server. Return value should be zero on an error, non-zero to proceed. Also,
  * callbacks should themselves check if the id they generate is unique otherwise
  * the SSL handshake will fail with an error - callbacks can do this using the
  * 'ssl' value they're passed by;
  *      SSL_has_matching_session_id(ssl, id, *id_len)
  * The length value passed in is set at the maximum size the session ID can be.
  * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
  * can alter this length to be less if desired, but under SSLv2 session IDs are
  * supposed to be fixed at 16 bytes so the id will be padded after the callback
  * returns in this case. It is also an error for the callback to set the size to
  * zero. */
 typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len);
 
 typedef struct ssl_comp_st
 	{
 	int id;
 	const char *name;
 #ifndef OPENSSL_NO_COMP
 	COMP_METHOD *method;
 #else
 	char *method;
 #endif
 	} SSL_COMP;
 
 DECLARE_STACK_OF(SSL_COMP)
 
 struct ssl_ctx_st
 	{
 	SSL_METHOD *method;
 
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	/* same as above but sorted for lookup */
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	struct x509_store_st /* X509_STORE */ *cert_store;
 	struct lhash_st /* LHASH */ *sessions;	/* a set of SSL_SESSIONs */
 	/* Most session-ids that will be cached, default is
 	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
 	unsigned long session_cache_size;
 	struct ssl_session_st *session_cache_head;
 	struct ssl_session_st *session_cache_tail;
 
 	/* This can have one of 2 values, ored together,
 	 * SSL_SESS_CACHE_CLIENT,
 	 * SSL_SESS_CACHE_SERVER,
 	 * Default is SSL_SESSION_CACHE_SERVER, which means only
 	 * SSL_accept which cache SSL_SESSIONS. */
 	int session_cache_mode;
 
 	/* If timeout is not 0, it is the default timeout value set
 	 * when SSL_new() is called.  This has been put in to make
 	 * life easier to set things up */
 	long session_timeout;
 
 	/* If this callback is not null, it will be called each
 	 * time a session id is added to the cache.  If this function
 	 * returns 1, it means that the callback will do a
 	 * SSL_SESSION_free() when it has finished using it.  Otherwise,
 	 * on 0, it means the callback has finished with it.
 	 * If remove_session_cb is not null, it will be called when
 	 * a session-id is removed from the cache.  After the call,
 	 * OpenSSL will SSL_SESSION_free() it. */
 	int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
 	void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
 	SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
 		unsigned char *data,int len,int *copy);
 
 	struct
 		{
 		int sess_connect;	/* SSL new conn - started */
 		int sess_connect_renegotiate;/* SSL reneg - requested */
 		int sess_connect_good;	/* SSL new conne/reneg - finished */
 		int sess_accept;	/* SSL new accept - started */
 		int sess_accept_renegotiate;/* SSL reneg - requested */
 		int sess_accept_good;	/* SSL accept/reneg - finished */
 		int sess_miss;		/* session lookup misses  */
 		int sess_timeout;	/* reuse attempt on timeouted session */
 		int sess_cache_full;	/* session removed due to full cache */
 		int sess_hit;		/* session reuse actually done */
 		int sess_cb_hit;	/* session-id that was not
 					 * in the cache was
 					 * passed back via the callback.  This
 					 * indicates that the application is
 					 * supplying session-id's from other
 					 * processes - spooky :-) */
 		} stats;
 
 	int references;
 
 	/* if defined, these override the X509_verify_cert() calls */
 	int (*app_verify_callback)(X509_STORE_CTX *, void *);
 	void *app_verify_arg;
 	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
 	 * ('app_verify_callback' was called with just one argument) */
 
 	/* Default password callback. */
 	pem_password_cb *default_passwd_callback;
 
 	/* Default password callback user data. */
 	void *default_passwd_callback_userdata;
 
 	/* get client cert callback */
 	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 
     /* cookie generate callback */
     int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int *cookie_len);
 
     /* verify cookie callback */
     int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, 
         unsigned int cookie_len);
 
 	CRYPTO_EX_DATA ex_data;
 
 	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
 	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */
 	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */
 
 	STACK_OF(X509) *extra_certs;
 	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
 
 
 	/* Default values used when no per-SSL value is defined follow */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
 
 	/* what we put in client cert requests */
 	STACK_OF(X509_NAME) *client_CA;
 
 
 	/* Default values to use in SSL structures follow (these are copied by SSL_new) */
 
 	unsigned long options;
 	unsigned long mode;
 	long max_cert_list;
 
 	struct cert_st /* CERT */ *cert;
 	int read_ahead;
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int verify_mode;
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	int quiet_shutdown;
 
 #ifndef OPENSSL_ENGINE
 	/* Engine to pass requests for client certs to
 	 */
 	ENGINE *client_cert_engine;
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extensions servername callback */
 	int (*tlsext_servername_callback)(SSL*, int *, void *);
 	void *tlsext_servername_arg;
 	/* RFC 4507 session ticket keys */
 	unsigned char tlsext_tick_key_name[16];
 	unsigned char tlsext_tick_hmac_key[16];
 	unsigned char tlsext_tick_aes_key[16];
 	/* Callback to support customisation of ticket key setting */
 	int (*tlsext_ticket_key_cb)(SSL *ssl,
 					unsigned char *name, unsigned char *iv,
 					EVP_CIPHER_CTX *ectx,
 					HMAC_CTX *hctx, int enc);
 
 	/* certificate status request info */
 	/* Callback for status request */
 	int (*tlsext_status_cb)(SSL *ssl, void *arg);
 	void *tlsext_status_arg;
 #endif
 
 	};
 
 #define SSL_SESS_CACHE_OFF			0x0000
 #define SSL_SESS_CACHE_CLIENT			0x0001
 #define SSL_SESS_CACHE_SERVER			0x0002
 #define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
 #define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080
 /* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
 #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100
 #define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200
 #define SSL_SESS_CACHE_NO_INTERNAL \
 	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
 
   struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
 #define SSL_CTX_sess_number(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
 #define SSL_CTX_sess_connect(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
 #define SSL_CTX_sess_connect_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
 #define SSL_CTX_sess_connect_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
 #define SSL_CTX_sess_accept_renegotiate(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
 #define SSL_CTX_sess_accept_good(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
 #define SSL_CTX_sess_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
 #define SSL_CTX_sess_cb_hits(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
 #define SSL_CTX_sess_misses(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
 #define SSL_CTX_sess_timeouts(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
 #define SSL_CTX_sess_cache_full(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
 SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
 #endif
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
 
 #define SSL_NOTHING	1
 #define SSL_WRITING	2
 #define SSL_READING	3
 #define SSL_X509_LOOKUP	4
 
 /* These will only be used when doing non-blocking IO */
 #define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
 #define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
 #define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
 #define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
 
 struct ssl_st
 	{
 	/* protocol version
 	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
 	 */
 	int version;
 	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
 
 	SSL_METHOD *method; /* SSLv3 */
 
 	/* There are 2 BIO's even though they are normally both the
 	 * same.  This is so data can be read and written to different
 	 * handlers */
 
 #ifndef OPENSSL_NO_BIO
 	BIO *rbio; /* used by SSL_read */
 	BIO *wbio; /* used by SSL_write */
 	BIO *bbio; /* used during session-id reuse to concatenate
 		    * messages */
 #else
 	char *rbio; /* used by SSL_read */
 	char *wbio; /* used by SSL_write */
 	char *bbio;
 #endif
 	/* This holds a variable that indicates what we were doing
 	 * when a 0 or -1 is returned.  This is needed for
 	 * non-blocking IO so we know what request needs re-doing when
 	 * in SSL_accept or SSL_connect */
 	int rwstate;
 
 	/* true when we are actually in SSL_accept() or SSL_connect() */
 	int in_handshake;
 	int (*handshake_func)(SSL *);
 
 	/* Imagine that here's a boolean member "init" that is
 	 * switched as soon as SSL_set_{accept/connect}_state
 	 * is called for the first time, so that "state" and
 	 * "handshake_func" are properly initialized.  But as
 	 * handshake_func is == 0 until then, we use this
 	 * test instead of an "init" member.
 	 */
 
 	int server;	/* are we the server side? - mostly used by SSL_clear*/
 
 	int new_session;/* 1 if we are to use a new session.
 	                 * 2 if we are a server and are inside a handshake
 	                 *   (i.e. not just sending a HelloRequest)
 	                 * NB: For servers, the 'new' session may actually be a previously
 	                 * cached session or even the previous session unless
 	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 	int quiet_shutdown;/* don't send shutdown packets */
 	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
 			 * for received */
 	int state;	/* where we are */
 	int rstate;	/* where we are when reading */
 
 	BUF_MEM *init_buf;	/* buffer used during init */
 	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */
 	int init_num;		/* amount read/written */
 	int init_off;		/* amount read/written */
 
 	/* used internally to point at a raw packet */
 	unsigned char *packet;
 	unsigned int packet_length;
 
 	struct ssl2_state_st *s2; /* SSLv2 variables */
 	struct ssl3_state_st *s3; /* SSLv3 variables */
 	struct dtls1_state_st *d1; /* DTLSv1 variables */
 
 	int read_ahead;		/* Read as many input bytes as possible
 	               	 	 * (for non-blocking reads) */
 
 	/* callback that allows applications to peek at protocol messages */
 	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 	void *msg_callback_arg;
 
 	int hit;		/* reusing a previous session */
 
 	X509_VERIFY_PARAM *param;
 
 #if 0
 	int purpose;		/* Purpose setting */
 	int trust;		/* Trust setting */
 #endif
 
 	/* crypto */
 	STACK_OF(SSL_CIPHER) *cipher_list;
 	STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 	/* These are the ones being used, the ones in SSL_SESSION are
 	 * the ones to be 'copied' into these ones */
 
 	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */
 	const EVP_MD *read_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *expand;			/* uncompress */
 #else
 	char *expand;
 #endif
 
 	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */
 	const EVP_MD *write_hash;		/* used for mac generation */
 #ifndef OPENSSL_NO_COMP
 	COMP_CTX *compress;			/* compression */
 #else
 	char *compress;	
 #endif
 
 	/* session info */
 
 	/* client cert? */
 	/* This is used to hold the server certificate used */
 	struct cert_st /* CERT */ *cert;
 
 	/* the session_id_context is used to ensure sessions are only reused
 	 * in the appropriate context */
 	unsigned int sid_ctx_length;
 	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 	/* This can also be in the session once a session is established */
 	SSL_SESSION *session;
 
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;
 
 	/* Used in SSL2 and SSL3 */
 	int verify_mode;	/* 0 don't care about verify failure.
 				 * 1 fail if verify fails */
 	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
 
 	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
 
 	int error;		/* error bytes to be written */
 	int error_code;		/* actual code */
 
 #ifndef OPENSSL_NO_KRB5
 	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
 #endif	/* OPENSSL_NO_KRB5 */
 
 	SSL_CTX *ctx;
 	/* set this flag to 1 and a sleep(1) is put into all SSL_read()
 	 * and SSL_write() calls, good for nbio debuging :-) */
 	int debug;	
 
 	/* extra application data */
 	long verify_result;
 	CRYPTO_EX_DATA ex_data;
 
 	/* for server side, keep the list of CA_dn we can use */
 	STACK_OF(X509_NAME) *client_CA;
 
 	int references;
 	unsigned long options; /* protocol behaviour */
 	unsigned long mode; /* API behaviour */
 	long max_cert_list;
 	int first_packet;
 	int client_version;	/* what was passed, used for
 				 * SSLv3/TLS rollback check */
 #ifndef OPENSSL_NO_TLSEXT
 	/* TLS extension debug callback */
 	void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
 					unsigned char *data, int len,
 					void *arg);
 	void *tlsext_debug_arg;
 	char *tlsext_hostname;
 	int servername_done;   /* no further mod of servername 
 	                          0 : call the servername extension callback.
 	                          1 : prepare 2, allow last ack just after in server callback.
 	                          2 : don't call servername callback, no ack in server hello
 	                       */
 	/* certificate status request info */
 	/* Status type or -1 if no status type */
 	int tlsext_status_type;
 	/* Expect OCSP CertificateStatus message */
 	int tlsext_status_expected;
 	/* OCSP status request only */
 	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
 	X509_EXTENSIONS *tlsext_ocsp_exts;
 	/* OCSP response received or to be sent */
 	unsigned char *tlsext_ocsp_resp;
 	int tlsext_ocsp_resplen;
 
 	/* RFC4507 session ticket expected to be received or sent */
 	int tlsext_ticket_expected;
 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
 #define session_ctx initial_ctx
 #else
 #define session_ctx ctx
 #endif
 	};
 
 #ifdef __cplusplus
 }
 #endif
 
 #include 
 #include 
 #include  /* This is mostly sslv3 with a few tweaks */
 #include  /* Datagram TLS */
 #include 
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
 /* compatibility */
 #define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg))
 #define SSL_get_app_data(s)		(SSL_get_ex_data(s,0))
 #define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a))
 #define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0))
 #define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0))
 #define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg))
 
 /* The following are the possible values for ssl->state are are
  * used to indicate where we are up to in the SSL connection establishment.
  * The macros that follow are about the only things you should need to use
  * and even then, only when using non-blocking IO.
  * It can also be useful to work out where you were when the connection
  * failed */
 
 #define SSL_ST_CONNECT			0x1000
 #define SSL_ST_ACCEPT			0x2000
 #define SSL_ST_MASK			0x0FFF
 #define SSL_ST_INIT			(SSL_ST_CONNECT|SSL_ST_ACCEPT)
 #define SSL_ST_BEFORE			0x4000
 #define SSL_ST_OK			0x03
 #define SSL_ST_RENEGOTIATE		(0x04|SSL_ST_INIT)
 
 #define SSL_CB_LOOP			0x01
 #define SSL_CB_EXIT			0x02
 #define SSL_CB_READ			0x04
 #define SSL_CB_WRITE			0x08
 #define SSL_CB_ALERT			0x4000 /* used in callback */
 #define SSL_CB_READ_ALERT		(SSL_CB_ALERT|SSL_CB_READ)
 #define SSL_CB_WRITE_ALERT		(SSL_CB_ALERT|SSL_CB_WRITE)
 #define SSL_CB_ACCEPT_LOOP		(SSL_ST_ACCEPT|SSL_CB_LOOP)
 #define SSL_CB_ACCEPT_EXIT		(SSL_ST_ACCEPT|SSL_CB_EXIT)
 #define SSL_CB_CONNECT_LOOP		(SSL_ST_CONNECT|SSL_CB_LOOP)
 #define SSL_CB_CONNECT_EXIT		(SSL_ST_CONNECT|SSL_CB_EXIT)
 #define SSL_CB_HANDSHAKE_START		0x10
 #define SSL_CB_HANDSHAKE_DONE		0x20
 
 /* Is the SSL_connection established? */
 #define SSL_get_state(a)		SSL_state(a)
 #define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
 #define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
 #define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
 #define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
 #define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
  * you should not need these */
 #define SSL_ST_READ_HEADER			0xF0
 #define SSL_ST_READ_BODY			0xF1
 #define SSL_ST_READ_DONE			0xF2
 
 /* Obtain latest Finished message
  *   -- that we sent (SSL_get_finished)
  *   -- that we expected from peer (SSL_get_peer_finished).
  * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
 size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
 size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 
 /* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
  * are 'ored' with SSL_VERIFY_PEER if they are desired */
 #define SSL_VERIFY_NONE			0x00
 #define SSL_VERIFY_PEER			0x01
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
 #define SSL_VERIFY_CLIENT_ONCE		0x04
 
 #define OpenSSL_add_ssl_algorithms()	SSL_library_init()
 #define SSLeay_add_ssl_algorithms()	SSL_library_init()
 
 /* this is for backward compatibility */
 #if 0 /* NEW_SSLEAY */
 #define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
 #define SSL_set_pref_cipher(c,n)	SSL_set_cipher_list(c,n)
 #define SSL_add_session(a,b)            SSL_CTX_add_session((a),(b))
 #define SSL_remove_session(a,b)		SSL_CTX_remove_session((a),(b))
 #define SSL_flush_sessions(a,b)		SSL_CTX_flush_sessions((a),(b))
 #endif
 /* More backward compatibility */
 #define SSL_get_cipher(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_cipher_bits(s,np) \
 		SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
 #define SSL_get_cipher_version(s) \
 		SSL_CIPHER_get_version(SSL_get_current_cipher(s))
 #define SSL_get_cipher_name(s) \
 		SSL_CIPHER_get_name(SSL_get_current_cipher(s))
 #define SSL_get_time(a)		SSL_SESSION_get_time(a)
 #define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b))
 #define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a)
 #define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b))
 
 #if 1 /*SSLEAY_MACROS*/
 #define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
 #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
 #define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
 	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
 #define PEM_read_bio_SSL_SESSION(bp,x,cb,u) PEM_ASN1_read_bio_of(SSL_SESSION,d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,cb,u)
 #define PEM_write_SSL_SESSION(fp,x) \
 	PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
 		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_SSL_SESSION(bp,x) \
 	PEM_ASN1_write_bio_of(SSL_SESSION,i2d_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,NULL,NULL,0,NULL,NULL)
 #endif
 
 #define SSL_AD_REASON_OFFSET		1000
 /* These alert types are for SSLv3 and TLSv1 */
 #define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY
 #define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
 #define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */
 #define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED
 #define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW
 #define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
 #define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */
 #define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */
 #define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE
 #define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE
 #define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED
 #define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED
 #define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN
 #define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */
 #define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */
 #define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */
 #define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */
 #define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR
 #define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */
 #define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */
 #define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
 #define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */
 #define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION
 #define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION
 #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 #define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME
 #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY	TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
 #define SSL_AD_INAPPROPRIATE_FALLBACK	TLS1_AD_INAPPROPRIATE_FALLBACK /* fatal */
 
 #define SSL_ERROR_NONE			0
 #define SSL_ERROR_SSL			1
 #define SSL_ERROR_WANT_READ		2
 #define SSL_ERROR_WANT_WRITE		3
 #define SSL_ERROR_WANT_X509_LOOKUP	4
 #define SSL_ERROR_SYSCALL		5 /* look at error stack/return value/errno */
 #define SSL_ERROR_ZERO_RETURN		6
 #define SSL_ERROR_WANT_CONNECT		7
 #define SSL_ERROR_WANT_ACCEPT		8
 
 #define SSL_CTRL_NEED_TMP_RSA			1
 #define SSL_CTRL_SET_TMP_RSA			2
 #define SSL_CTRL_SET_TMP_DH			3
 #define SSL_CTRL_SET_TMP_ECDH			4
 #define SSL_CTRL_SET_TMP_RSA_CB			5
 #define SSL_CTRL_SET_TMP_DH_CB			6
 #define SSL_CTRL_SET_TMP_ECDH_CB		7
 
 #define SSL_CTRL_GET_SESSION_REUSED		8
 #define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9
 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10
 #define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11
 #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12
 #define SSL_CTRL_GET_FLAGS			13
 #define SSL_CTRL_EXTRA_CHAIN_CERT		14
 
 #define SSL_CTRL_SET_MSG_CALLBACK               15
 #define SSL_CTRL_SET_MSG_CALLBACK_ARG           16
 
 /* only applies to datagram connections */
 #define SSL_CTRL_SET_MTU                17
 /* Stats */
 #define SSL_CTRL_SESS_NUMBER			20
 #define SSL_CTRL_SESS_CONNECT			21
 #define SSL_CTRL_SESS_CONNECT_GOOD		22
 #define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23
 #define SSL_CTRL_SESS_ACCEPT			24
 #define SSL_CTRL_SESS_ACCEPT_GOOD		25
 #define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26
 #define SSL_CTRL_SESS_HIT			27
 #define SSL_CTRL_SESS_CB_HIT			28
 #define SSL_CTRL_SESS_MISSES			29
 #define SSL_CTRL_SESS_TIMEOUTS			30
 #define SSL_CTRL_SESS_CACHE_FULL		31
 #define SSL_CTRL_OPTIONS			32
 #define SSL_CTRL_MODE				33
 
 #define SSL_CTRL_GET_READ_AHEAD			40
 #define SSL_CTRL_SET_READ_AHEAD			41
 #define SSL_CTRL_SET_SESS_CACHE_SIZE		42
 #define SSL_CTRL_GET_SESS_CACHE_SIZE		43
 #define SSL_CTRL_SET_SESS_CACHE_MODE		44
 #define SSL_CTRL_GET_SESS_CACHE_MODE		45
 
 #define SSL_CTRL_GET_MAX_CERT_LIST		50
 #define SSL_CTRL_SET_MAX_CERT_LIST		51
 
 /* see tls1.h for macros based on these */
 #ifndef OPENSSL_NO_TLSEXT
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB	53
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG	54
 #define SSL_CTRL_SET_TLSEXT_HOSTNAME		55
 #define SSL_CTRL_SET_TLSEXT_DEBUG_CB		56
 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57
 #define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59
 
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71
 
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72
 #endif
 
 #define DTLS_CTRL_GET_TIMEOUT		73
 #define DTLS_CTRL_HANDLE_TIMEOUT	74
 #define DTLS_CTRL_LISTEN			75
 
 #define SSL_CTRL_GET_RI_SUPPORT			76
 #define SSL_CTRL_CLEAR_OPTIONS			77
 #define SSL_CTRL_CLEAR_MODE			78
 
 #define SSL_CTRL_CHECK_PROTO_VERSION		119
 
 #define DTLSv1_get_timeout(ssl, arg) \
 	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
 #define DTLSv1_handle_timeout(ssl) \
 	SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
 #define DTLSv1_listen(ssl, peer) \
 	SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
 
 #define SSL_session_reused(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
 #define SSL_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_clear_num_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
 #define SSL_total_renegotiations(ssl) \
 	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
 
 #define SSL_CTX_need_tmp_RSA(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_CTX_set_tmp_rsa(ctx,rsa) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_CTX_set_tmp_dh(ctx,dh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_need_tmp_RSA(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
 #define SSL_set_tmp_rsa(ssl,rsa) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
 #define SSL_set_tmp_dh(ssl,dh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 #define SSL_set_tmp_ecdh(ssl,ecdh) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
 
 #define SSL_CTX_add_extra_chain_cert(ctx,x509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
 
 #ifndef OPENSSL_NO_BIO
 BIO_METHOD *BIO_f_ssl(void);
 BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
 BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
 BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
 int BIO_ssl_copy_session_id(BIO *to,BIO *from);
 void BIO_ssl_shutdown(BIO *ssl_bio);
 
 #endif
 
 int	SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
 SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
 void	SSL_CTX_free(SSL_CTX *);
 long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
 long SSL_CTX_get_timeout(const SSL_CTX *ctx);
 X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
 void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
 int SSL_want(const SSL *s);
 int	SSL_clear(SSL *s);
 
 void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
 
 SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
 int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
 char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
 const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
 
 int	SSL_get_fd(const SSL *s);
 int	SSL_get_rfd(const SSL *s);
 int	SSL_get_wfd(const SSL *s);
 const char  * SSL_get_cipher_list(const SSL *s,int n);
 char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
 int	SSL_get_read_ahead(const SSL * s);
 int	SSL_pending(const SSL *s);
 #ifndef OPENSSL_NO_SOCK
 int	SSL_set_fd(SSL *s, int fd);
 int	SSL_set_rfd(SSL *s, int fd);
 int	SSL_set_wfd(SSL *s, int fd);
 #endif
 #ifndef OPENSSL_NO_BIO
 void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
 BIO *	SSL_get_rbio(const SSL *s);
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
 int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
 void	SSL_set_verify(SSL *s, int mode,
 		       int (*callback)(int ok,X509_STORE_CTX *ctx));
 void	SSL_set_verify_depth(SSL *s, int depth);
 #ifndef OPENSSL_NO_RSA
 int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
 #endif
 int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
 int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
 
 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
 int	SSL_use_certificate_file(SSL *ssl, const char *file, int type);
 int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
 int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
 STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
 int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					    const char *file);
 #ifndef OPENSSL_SYS_VMS
 #ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
 int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 					   const char *dir);
 #endif
 #endif
 
 #endif
 
 void	SSL_load_error_strings(void );
 const char *SSL_state_string(const SSL *s);
 const char *SSL_rstate_string(const SSL *s);
 const char *SSL_state_string_long(const SSL *s);
 const char *SSL_rstate_string_long(const SSL *s);
 long	SSL_SESSION_get_time(const SSL_SESSION *s);
 long	SSL_SESSION_set_time(SSL_SESSION *s, long t);
 long	SSL_SESSION_get_timeout(const SSL_SESSION *s);
 long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
 void	SSL_copy_session_id(SSL *to,const SSL *from);
 
 SSL_SESSION *SSL_SESSION_new(void);
 unsigned long SSL_SESSION_hash(const SSL_SESSION *a);
 int	SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len);
 #ifndef OPENSSL_NO_FP_API
 int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
 #endif
 #ifndef OPENSSL_NO_BIO
 int	SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
 #endif
 void	SSL_SESSION_free(SSL_SESSION *ses);
 int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
 int	SSL_set_session(SSL *to, SSL_SESSION *session);
 int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
 int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
 int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
 int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
 int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
 					unsigned int id_len);
 SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
 			     long length);
 
 #ifdef HEADER_X509_H
 X509 *	SSL_get_peer_certificate(const SSL *s);
 #endif
 
 STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
 
 int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
 int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
 int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
 void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
 			int (*callback)(int, X509_STORE_CTX *));
 void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
 void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
 #ifndef OPENSSL_NO_RSA
 int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
 #endif
 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
 int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
 	const unsigned char *d, long len);
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
 
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
 
 int SSL_CTX_check_private_key(const SSL_CTX *ctx);
 int SSL_check_private_key(const SSL *ctx);
 
 int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
 				       unsigned int sid_ctx_len);
 
 SSL *	SSL_new(SSL_CTX *ctx);
 int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
 				   unsigned int sid_ctx_len);
 
 int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
 int SSL_set_purpose(SSL *s, int purpose);
 int SSL_CTX_set_trust(SSL_CTX *s, int trust);
 int SSL_set_trust(SSL *s, int trust);
 
 void	SSL_free(SSL *ssl);
 int 	SSL_accept(SSL *ssl);
 int 	SSL_connect(SSL *ssl);
 int 	SSL_read(SSL *ssl,void *buf,int num);
 int 	SSL_peek(SSL *ssl,void *buf,int num);
 int 	SSL_write(SSL *ssl,const void *buf,int num);
 long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
 long	SSL_callback_ctrl(SSL *, int, void (*)(void));
 long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
 long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
 
 int	SSL_get_error(const SSL *s,int ret_code);
 const char *SSL_get_version(const SSL *s);
 
 /* This sets the 'default' SSL version that SSL_new() will create */
 int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
 
 SSL_METHOD *SSLv2_method(void);		/* SSLv2 */
 SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */
 SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
 
 SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
 SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
 SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
 
 SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */
 SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */
 SSL_METHOD *SSLv23_client_method(void);	/* SSLv3 but can rollback to v2 */
 
 SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */
 SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */
 SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */
 
 SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */
 SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */
 SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */
 
 STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
 
 int SSL_do_handshake(SSL *s);
 int SSL_renegotiate(SSL *s);
 int SSL_renegotiate_pending(SSL *s);
 int SSL_shutdown(SSL *s);
 
 SSL_METHOD *SSL_get_ssl_method(SSL *s);
 int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
 const char *SSL_alert_type_string_long(int value);
 const char *SSL_alert_type_string(int value);
 const char *SSL_alert_desc_string_long(int value);
 const char *SSL_alert_desc_string(int value);
 
 void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
 void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
 STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
 STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
 int SSL_add_client_CA(SSL *ssl,X509 *x);
 int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
 
 void SSL_set_connect_state(SSL *s);
 void SSL_set_accept_state(SSL *s);
 
 long SSL_get_default_timeout(const SSL *s);
 
 int SSL_library_init(void );
 
 char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
 STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
 
 SSL *SSL_dup(SSL *ssl);
 
 X509 *SSL_get_certificate(const SSL *ssl);
 /* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
 
 void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
 int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
 void SSL_set_quiet_shutdown(SSL *ssl,int mode);
 int SSL_get_quiet_shutdown(const SSL *ssl);
 void SSL_set_shutdown(SSL *ssl,int mode);
 int SSL_get_shutdown(const SSL *ssl);
 int SSL_version(const SSL *ssl);
 int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
 int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
 	const char *CApath);
 #define SSL_get0_session SSL_get_session /* just peek at pointer */
 SSL_SESSION *SSL_get_session(const SSL *ssl);
 SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
 SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
 SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
 void SSL_set_info_callback(SSL *ssl,
 			   void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
 int SSL_state(const SSL *ssl);
 
 void SSL_set_verify_result(SSL *ssl,long v);
 long SSL_get_verify_result(const SSL *ssl);
 
 int SSL_set_ex_data(SSL *ssl,int idx,void *data);
 void *SSL_get_ex_data(const SSL *ssl,int idx);
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
 void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
 int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
 
 int SSL_get_ex_data_X509_STORE_CTX_idx(void );
 
 #define SSL_CTX_sess_set_cache_size(ctx,t) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
 #define SSL_CTX_sess_get_cache_size(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
 #define SSL_CTX_set_session_cache_mode(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
 #define SSL_CTX_get_session_cache_mode(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
 
 #define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
 #define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
 #define SSL_CTX_get_read_ahead(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
 #define SSL_CTX_set_read_ahead(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
 #define SSL_CTX_get_max_cert_list(ctx) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_CTX_set_max_cert_list(ctx,m) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 #define SSL_get_max_cert_list(ssl) \
 	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
 #define SSL_set_max_cert_list(ssl,m) \
 	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
 
      /* NB: the keylength is only applicable when is_export is true */
 #ifndef OPENSSL_NO_RSA
 void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 
 void SSL_set_tmp_rsa_callback(SSL *ssl,
 				  RSA *(*cb)(SSL *ssl,int is_export,
 					     int keylength));
 #endif
 #ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_dh_callback(SSL *ssl,
 				 DH *(*dh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 #ifndef OPENSSL_NO_ECDH
 void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 void SSL_set_tmp_ecdh_callback(SSL *ssl,
 				 EC_KEY *(*ecdh)(SSL *ssl,int is_export,
 					   int keylength));
 #endif
 
 #ifndef OPENSSL_NO_COMP
 const COMP_METHOD *SSL_get_current_compression(SSL *s);
 const COMP_METHOD *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const COMP_METHOD *comp);
 STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
 #else
 const void *SSL_get_current_compression(SSL *s);
 const void *SSL_get_current_expansion(SSL *s);
 const char *SSL_COMP_get_name(const void *comp);
 void *SSL_COMP_get_compression_methods(void);
 int SSL_COMP_add_compression_method(int id,void *cm);
 #endif
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
 void ERR_load_SSL_strings(void);
 
 /* Error codes for the SSL functions. */
 
 /* Function codes. */
 #define SSL_F_CLIENT_CERTIFICATE			 100
 #define SSL_F_CLIENT_FINISHED				 167
 #define SSL_F_CLIENT_HELLO				 101
 #define SSL_F_CLIENT_MASTER_KEY				 102
 #define SSL_F_D2I_SSL_SESSION				 103
 #define SSL_F_DO_DTLS1_WRITE				 245
 #define SSL_F_DO_SSL3_WRITE				 104
 #define SSL_F_DTLS1_ACCEPT				 246
 #define SSL_F_DTLS1_ADD_CERT_TO_BUF			 280
 #define SSL_F_DTLS1_BUFFER_RECORD			 247
 #define SSL_F_DTLS1_CHECK_TIMEOUT_NUM			 293
 #define SSL_F_DTLS1_CLIENT_HELLO			 248
 #define SSL_F_DTLS1_CONNECT				 249
 #define SSL_F_DTLS1_ENC					 250
 #define SSL_F_DTLS1_GET_HELLO_VERIFY			 251
 #define SSL_F_DTLS1_GET_MESSAGE				 252
 #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253
 #define SSL_F_DTLS1_GET_RECORD				 254
 #define SSL_F_DTLS1_HANDLE_TIMEOUT			 282
 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255
 #define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 277
 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256
 #define SSL_F_DTLS1_PROCESS_RECORD			 257
 #define SSL_F_DTLS1_READ_BYTES				 258
 #define SSL_F_DTLS1_READ_FAILED				 259
 #define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260
 #define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261
 #define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262
 #define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263
 #define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264
 #define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265
 #define SSL_F_DTLS1_SEND_SERVER_HELLO			 266
 #define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267
 #define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268
 #define SSL_F_GET_CLIENT_FINISHED			 105
 #define SSL_F_GET_CLIENT_HELLO				 106
 #define SSL_F_GET_CLIENT_MASTER_KEY			 107
 #define SSL_F_GET_SERVER_FINISHED			 108
 #define SSL_F_GET_SERVER_HELLO				 109
 #define SSL_F_GET_SERVER_VERIFY				 110
 #define SSL_F_I2D_SSL_SESSION				 111
 #define SSL_F_READ_N					 112
 #define SSL_F_REQUEST_CERTIFICATE			 113
 #define SSL_F_SERVER_FINISH				 239
 #define SSL_F_SERVER_HELLO				 114
 #define SSL_F_SERVER_VERIFY				 240
 #define SSL_F_SSL23_ACCEPT				 115
 #define SSL_F_SSL23_CLIENT_HELLO			 116
 #define SSL_F_SSL23_CONNECT				 117
 #define SSL_F_SSL23_GET_CLIENT_HELLO			 118
 #define SSL_F_SSL23_GET_SERVER_HELLO			 119
 #define SSL_F_SSL23_PEEK				 237
 #define SSL_F_SSL23_READ				 120
 #define SSL_F_SSL23_WRITE				 121
 #define SSL_F_SSL2_ACCEPT				 122
 #define SSL_F_SSL2_CONNECT				 123
 #define SSL_F_SSL2_ENC_INIT				 124
 #define SSL_F_SSL2_GENERATE_KEY_MATERIAL		 241
 #define SSL_F_SSL2_PEEK					 234
 #define SSL_F_SSL2_READ					 125
 #define SSL_F_SSL2_READ_INTERNAL			 236
 #define SSL_F_SSL2_SET_CERTIFICATE			 126
 #define SSL_F_SSL2_WRITE				 127
 #define SSL_F_SSL3_ACCEPT				 128
 #define SSL_F_SSL3_ADD_CERT_TO_BUF			 281
 #define SSL_F_SSL3_CALLBACK_CTRL			 233
 #define SSL_F_SSL3_CHANGE_CIPHER_STATE			 129
 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM		 130
 #define SSL_F_SSL3_CHECK_CLIENT_HELLO			 292
 #define SSL_F_SSL3_CLIENT_HELLO				 131
 #define SSL_F_SSL3_CONNECT				 132
 #define SSL_F_SSL3_CTRL					 213
 #define SSL_F_SSL3_CTX_CTRL				 133
 #define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 279
 #define SSL_F_SSL3_ENC					 134
 #define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238
 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135
 #define SSL_F_SSL3_GET_CERT_STATUS			 288
 #define SSL_F_SSL3_GET_CERT_VERIFY			 136
 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE		 137
 #define SSL_F_SSL3_GET_CLIENT_HELLO			 138
 #define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE		 139
 #define SSL_F_SSL3_GET_FINISHED				 140
 #define SSL_F_SSL3_GET_KEY_EXCHANGE			 141
 #define SSL_F_SSL3_GET_MESSAGE				 142
 #define SSL_F_SSL3_GET_NEW_SESSION_TICKET		 283
 #define SSL_F_SSL3_GET_RECORD				 143
 #define SSL_F_SSL3_GET_SERVER_CERTIFICATE		 144
 #define SSL_F_SSL3_GET_SERVER_DONE			 145
 #define SSL_F_SSL3_GET_SERVER_HELLO			 146
 #define SSL_F_SSL3_NEW_SESSION_TICKET			 284
 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147
 #define SSL_F_SSL3_PEEK					 235
 #define SSL_F_SSL3_READ_BYTES				 148
 #define SSL_F_SSL3_READ_N				 149
 #define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST		 150
 #define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE		 151
 #define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE		 152
 #define SSL_F_SSL3_SEND_CLIENT_VERIFY			 153
 #define SSL_F_SSL3_SEND_SERVER_CERTIFICATE		 154
 #define SSL_F_SSL3_SEND_SERVER_HELLO			 242
 #define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155
 #define SSL_F_SSL3_SETUP_BUFFERS			 156
 #define SSL_F_SSL3_SETUP_KEY_BLOCK			 157
 #define SSL_F_SSL3_WRITE_BYTES				 158
 #define SSL_F_SSL3_WRITE_PENDING			 159
 #define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 285
 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 272
 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215
 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216
 #define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT	 286
 #define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 273
 #define SSL_F_SSL_BAD_METHOD				 160
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
 #define SSL_F_SSL_CERT_DUP				 221
 #define SSL_F_SSL_CERT_INST				 222
 #define SSL_F_SSL_CERT_INSTANTIATE			 214
 #define SSL_F_SSL_CERT_NEW				 162
 #define SSL_F_SSL_CHECK_PRIVATE_KEY			 163
 #define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 274
 #define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230
 #define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231
 #define SSL_F_SSL_CLEAR					 164
 #define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165
 #define SSL_F_SSL_CREATE_CIPHER_LIST			 166
 #define SSL_F_SSL_CTRL					 232
 #define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
 #define SSL_F_SSL_CTX_NEW				 169
 #define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269
 #define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 278
 #define SSL_F_SSL_CTX_SET_PURPOSE			 226
 #define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
 #define SSL_F_SSL_CTX_SET_TRUST				 229
 #define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
 #define SSL_F_SSL_DO_HANDSHAKE				 180
 #define SSL_F_SSL_GET_NEW_SESSION			 181
 #define SSL_F_SSL_GET_PREV_SESSION			 217
 #define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
 #define SSL_F_SSL_GET_SERVER_SEND_PKEY			 317
 #define SSL_F_SSL_GET_SIGN_PKEY				 183
 #define SSL_F_SSL_INIT_WBIO_BUFFER			 184
 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
 #define SSL_F_SSL_NEW					 186
 #define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 287
 #define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 290
 #define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 289
 #define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 291
 #define SSL_F_SSL_PEEK					 270
 #define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 275
 #define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 276
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESS_CERT_NEW				 225
 #define SSL_F_SSL_SET_CERT				 191
 #define SSL_F_SSL_SET_CIPHER_LIST			 271
 #define SSL_F_SSL_SET_FD				 192
 #define SSL_F_SSL_SET_PKEY				 193
 #define SSL_F_SSL_SET_PURPOSE				 227
 #define SSL_F_SSL_SET_RFD				 194
 #define SSL_F_SSL_SET_SESSION				 195
 #define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
 #define SSL_F_SSL_SET_TRUST				 228
 #define SSL_F_SSL_SET_WFD				 196
 #define SSL_F_SSL_SHUTDOWN				 224
 #define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
 #define SSL_F_SSL_UNDEFINED_FUNCTION			 197
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
 #define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
 #define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
 #define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
 #define SSL_F_SSL_WRITE					 208
 #define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
 #define SSL_F_TLS1_ENC					 210
 #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
 #define SSL_F_WRITE_PENDING				 212
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
 #define SSL_R_BAD_ALERT_RECORD				 101
 #define SSL_R_BAD_AUTHENTICATION_TYPE			 102
 #define SSL_R_BAD_CHANGE_CIPHER_SPEC			 103
 #define SSL_R_BAD_CHECKSUM				 104
 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK		 106
 #define SSL_R_BAD_DECOMPRESSION				 107
 #define SSL_R_BAD_DH_G_LENGTH				 108
 #define SSL_R_BAD_DH_PUB_KEY_LENGTH			 109
 #define SSL_R_BAD_DH_P_LENGTH				 110
 #define SSL_R_BAD_DIGEST_LENGTH				 111
 #define SSL_R_BAD_DSA_SIGNATURE				 112
 #define SSL_R_BAD_ECC_CERT				 304
 #define SSL_R_BAD_ECDSA_SIGNATURE			 305
 #define SSL_R_BAD_ECPOINT				 306
 #define SSL_R_BAD_HELLO_REQUEST				 105
 #define SSL_R_BAD_LENGTH				 271
 #define SSL_R_BAD_MAC_DECODE				 113
 #define SSL_R_BAD_MESSAGE_TYPE				 114
 #define SSL_R_BAD_PACKET_LENGTH				 115
 #define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116
 #define SSL_R_BAD_RESPONSE_ARGUMENT			 117
 #define SSL_R_BAD_RSA_DECRYPT				 118
 #define SSL_R_BAD_RSA_ENCRYPT				 119
 #define SSL_R_BAD_RSA_E_LENGTH				 120
 #define SSL_R_BAD_RSA_MODULUS_LENGTH			 121
 #define SSL_R_BAD_RSA_SIGNATURE				 122
 #define SSL_R_BAD_SIGNATURE				 123
 #define SSL_R_BAD_SSL_FILETYPE				 124
 #define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125
 #define SSL_R_BAD_STATE					 126
 #define SSL_R_BAD_WRITE_RETRY				 127
 #define SSL_R_BIO_NOT_SET				 128
 #define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129
 #define SSL_R_BN_LIB					 130
 #define SSL_R_CA_DN_LENGTH_MISMATCH			 131
 #define SSL_R_CA_DN_TOO_LONG				 132
 #define SSL_R_CCS_RECEIVED_EARLY			 133
 #define SSL_R_CERTIFICATE_VERIFY_FAILED			 134
 #define SSL_R_CERT_LENGTH_MISMATCH			 135
 #define SSL_R_CHALLENGE_IS_DIFFERENT			 136
 #define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137
 #define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138
 #define SSL_R_CIPHER_TABLE_SRC_ERROR			 139
 #define SSL_R_CLIENTHELLO_TLSEXT			 157
 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140
 #define SSL_R_COMPRESSION_FAILURE			 141
 #define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307
 #define SSL_R_COMPRESSION_LIBRARY_ERROR			 142
 #define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143
 #define SSL_R_CONNECTION_TYPE_NOT_SET			 144
 #define SSL_R_COOKIE_MISMATCH				 308
 #define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145
 #define SSL_R_DATA_LENGTH_TOO_LONG			 146
 #define SSL_R_DECRYPTION_FAILED				 147
 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281
 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148
 #define SSL_R_DIGEST_CHECK_FAILED			 149
 #define SSL_R_DTLS_MESSAGE_TOO_BIG			 318
 #define SSL_R_DUPLICATE_COMPRESSION_ID			 309
 #define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310
 #define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150
 #define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282
 #define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151
 #define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152
 #define SSL_R_EXTRA_DATA_IN_MESSAGE			 153
 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154
 #define SSL_R_HTTPS_PROXY_REQUEST			 155
 #define SSL_R_HTTP_REQUEST				 156
 #define SSL_R_ILLEGAL_PADDING				 283
 #define SSL_R_INAPPROPRIATE_FALLBACK			 373
 #define SSL_R_INVALID_CHALLENGE_LENGTH			 158
 #define SSL_R_INVALID_COMMAND				 280
 #define SSL_R_INVALID_PURPOSE				 278
 #define SSL_R_INVALID_STATUS_RESPONSE			 316
 #define SSL_R_INVALID_TICKET_KEYS_LENGTH		 275
 #define SSL_R_INVALID_TRUST				 279
 #define SSL_R_KEY_ARG_TOO_LONG				 284
 #define SSL_R_KRB5					 285
 #define SSL_R_KRB5_C_CC_PRINC				 286
 #define SSL_R_KRB5_C_GET_CRED				 287
 #define SSL_R_KRB5_C_INIT				 288
 #define SSL_R_KRB5_C_MK_REQ				 289
 #define SSL_R_KRB5_S_BAD_TICKET				 290
 #define SSL_R_KRB5_S_INIT				 291
 #define SSL_R_KRB5_S_RD_REQ				 292
 #define SSL_R_KRB5_S_TKT_EXPIRED			 293
 #define SSL_R_KRB5_S_TKT_NYV				 294
 #define SSL_R_KRB5_S_TKT_SKEW				 295
 #define SSL_R_LENGTH_MISMATCH				 159
 #define SSL_R_LENGTH_TOO_SHORT				 160
 #define SSL_R_LIBRARY_BUG				 274
 #define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161
 #define SSL_R_MESSAGE_TOO_LONG				 296
 #define SSL_R_MISSING_DH_DSA_CERT			 162
 #define SSL_R_MISSING_DH_KEY				 163
 #define SSL_R_MISSING_DH_RSA_CERT			 164
 #define SSL_R_MISSING_DSA_SIGNING_CERT			 165
 #define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166
 #define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167
 #define SSL_R_MISSING_RSA_CERTIFICATE			 168
 #define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169
 #define SSL_R_MISSING_RSA_SIGNING_CERT			 170
 #define SSL_R_MISSING_TMP_DH_KEY			 171
 #define SSL_R_MISSING_TMP_ECDH_KEY			 311
 #define SSL_R_MISSING_TMP_RSA_KEY			 172
 #define SSL_R_MISSING_TMP_RSA_PKEY			 173
 #define SSL_R_MISSING_VERIFY_MESSAGE			 174
 #define SSL_R_MULTIPLE_SGC_RESTARTS			 325
 #define SSL_R_NON_SSLV2_INITIAL_PACKET			 175
 #define SSL_R_NO_CERTIFICATES_RETURNED			 176
 #define SSL_R_NO_CERTIFICATE_ASSIGNED			 177
 #define SSL_R_NO_CERTIFICATE_RETURNED			 178
 #define SSL_R_NO_CERTIFICATE_SET			 179
 #define SSL_R_NO_CERTIFICATE_SPECIFIED			 180
 #define SSL_R_NO_CIPHERS_AVAILABLE			 181
 #define SSL_R_NO_CIPHERS_PASSED				 182
 #define SSL_R_NO_CIPHERS_SPECIFIED			 183
 #define SSL_R_NO_CIPHER_LIST				 184
 #define SSL_R_NO_CIPHER_MATCH				 185
 #define SSL_R_NO_CLIENT_CERT_METHOD			 317
 #define SSL_R_NO_CLIENT_CERT_RECEIVED			 186
 #define SSL_R_NO_COMPRESSION_SPECIFIED			 187
 #define SSL_R_NO_METHOD_SPECIFIED			 188
 #define SSL_R_NO_PRIVATEKEY				 189
 #define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190
 #define SSL_R_NO_PROTOCOLS_AVAILABLE			 191
 #define SSL_R_NO_PUBLICKEY				 192
 #define SSL_R_NO_RENEGOTIATION				 319
 #define SSL_R_NO_SHARED_CIPHER				 193
 #define SSL_R_NO_VERIFY_CALLBACK			 194
 #define SSL_R_NULL_SSL_CTX				 195
 #define SSL_R_NULL_SSL_METHOD_PASSED			 196
 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
 #define SSL_R_PACKET_LENGTH_TOO_LONG			 198
 #define SSL_R_PARSE_TLSEXT				 223
 #define SSL_R_PATH_TOO_LONG				 270
 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199
 #define SSL_R_PEER_ERROR				 200
 #define SSL_R_PEER_ERROR_CERTIFICATE			 201
 #define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202
 #define SSL_R_PEER_ERROR_NO_CIPHER			 203
 #define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204
 #define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205
 #define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206
 #define SSL_R_PROTOCOL_IS_SHUTDOWN			 207
 #define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208
 #define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209
 #define SSL_R_PUBLIC_KEY_NOT_RSA			 210
 #define SSL_R_READ_BIO_NOT_SET				 211
 #define SSL_R_READ_TIMEOUT_EXPIRED			 312
 #define SSL_R_READ_WRONG_PACKET_TYPE			 212
 #define SSL_R_RECORD_LENGTH_MISMATCH			 213
 #define SSL_R_RECORD_TOO_LARGE				 214
 #define SSL_R_RECORD_TOO_SMALL				 298
 #define SSL_R_RENEGOTIATE_EXT_TOO_LONG			 320
 #define SSL_R_RENEGOTIATION_ENCODING_ERR		 321
 #define SSL_R_RENEGOTIATION_MISMATCH			 322
 #define SSL_R_REQUIRED_CIPHER_MISSING			 215
 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216
 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217
 #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218
 #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 324
 #define SSL_R_SERVERHELLO_TLSEXT			 224
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
 #define SSL_R_SHORT_READ				 219
 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
 #define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME		 225
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE		 226
 #define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300
 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222
 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE		 1042
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC		 1020
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED		 1045
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED		 1044
 #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN		 1046
 #define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE		 1030
 #define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE		 1040
 #define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER		 1047
 #define SSL_R_SSLV3_ALERT_NO_CERTIFICATE		 1041
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE		 1010
 #define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043
 #define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228
 #define SSL_R_SSL_HANDSHAKE_FAILURE			 229
 #define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230
 #define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301
 #define SSL_R_SSL_SESSION_ID_CONFLICT			 302
 #define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273
 #define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303
 #define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231
 #define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049
 #define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050
 #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021
 #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051
 #define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060
 #define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK	 1086
 #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071
 #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080
 #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100
 #define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070
 #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022
 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048
 #define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE		 1114
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE	 1113
 #define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE		 1111
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112
 #define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 227
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235
 #define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236
 #define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313
 #define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237
 #define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238
 #define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314
 #define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239
 #define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240
 #define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241
 #define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242
 #define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243
 #define SSL_R_UNEXPECTED_MESSAGE			 244
 #define SSL_R_UNEXPECTED_RECORD				 245
 #define SSL_R_UNINITIALIZED				 276
 #define SSL_R_UNKNOWN_ALERT_TYPE			 246
 #define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247
 #define SSL_R_UNKNOWN_CIPHER_RETURNED			 248
 #define SSL_R_UNKNOWN_CIPHER_TYPE			 249
 #define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250
 #define SSL_R_UNKNOWN_PKEY_TYPE				 251
 #define SSL_R_UNKNOWN_PROTOCOL				 252
 #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253
 #define SSL_R_UNKNOWN_SSL_VERSION			 254
 #define SSL_R_UNKNOWN_STATE				 255
 #define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 323
 #define SSL_R_UNSUPPORTED_CIPHER			 256
 #define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257
 #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315
 #define SSL_R_UNSUPPORTED_PROTOCOL			 258
 #define SSL_R_UNSUPPORTED_SSL_VERSION			 259
 #define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
 #define SSL_R_WRITE_BIO_NOT_SET				 260
 #define SSL_R_WRONG_CIPHER_RETURNED			 261
 #define SSL_R_WRONG_MESSAGE_TYPE			 262
 #define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263
 #define SSL_R_WRONG_SIGNATURE_LENGTH			 264
 #define SSL_R_WRONG_SIGNATURE_SIZE			 265
 #define SSL_R_WRONG_SSL_VERSION				 266
 #define SSL_R_WRONG_VERSION_NUMBER			 267
 #define SSL_R_X509_LIB					 268
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
 
 #ifdef  __cplusplus
 }
 #endif
 #endif
Index: releng/9.3/crypto/openssl/ssl/ssl_err.c
===================================================================
--- releng/9.3/crypto/openssl/ssl/ssl_err.c	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/ssl_err.c	(revision 284295)
@@ -1,545 +1,546 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
  * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 
 /* NOTE: this file was auto generated by the mkerr.pl script: any changes
  * made to it will be overwritten when the script next updates this file,
  * only reason strings will be preserved.
  */
 
 #include 
 #include 
 #include 
 
 /* BEGIN ERROR CODES */
 #ifndef OPENSSL_NO_ERR
 
 #define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0)
 #define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason)
 
 static ERR_STRING_DATA SSL_str_functs[]=
 	{
 {ERR_FUNC(SSL_F_CLIENT_CERTIFICATE),	"CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_CLIENT_FINISHED),	"CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_CLIENT_HELLO),	"CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_CLIENT_MASTER_KEY),	"CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_D2I_SSL_SESSION),	"d2i_SSL_SESSION"},
 {ERR_FUNC(SSL_F_DO_DTLS1_WRITE),	"DO_DTLS1_WRITE"},
 {ERR_FUNC(SSL_F_DO_SSL3_WRITE),	"DO_SSL3_WRITE"},
 {ERR_FUNC(SSL_F_DTLS1_ACCEPT),	"DTLS1_ACCEPT"},
 {ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF),	"DTLS1_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD),	"DTLS1_BUFFER_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM),	"DTLS1_CHECK_TIMEOUT_NUM"},
 {ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO),	"DTLS1_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_CONNECT),	"DTLS1_CONNECT"},
 {ERR_FUNC(SSL_F_DTLS1_ENC),	"DTLS1_ENC"},
 {ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY),	"DTLS1_GET_HELLO_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE),	"DTLS1_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT),	"DTLS1_HANDLE_TIMEOUT"},
 {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"},
 {ERR_FUNC(SSL_F_DTLS1_READ_FAILED),	"DTLS1_READ_FAILED"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST),	"DTLS1_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE),	"DTLS1_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE),	"DTLS1_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY),	"DTLS1_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),	"DTLS1_SEND_HELLO_VERIFY_REQUEST"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE),	"DTLS1_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO),	"DTLS1_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),	"DTLS1_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),	"DTLS1_WRITE_APP_DATA_BYTES"},
 {ERR_FUNC(SSL_F_GET_CLIENT_FINISHED),	"GET_CLIENT_FINISHED"},
 {ERR_FUNC(SSL_F_GET_CLIENT_HELLO),	"GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY),	"GET_CLIENT_MASTER_KEY"},
 {ERR_FUNC(SSL_F_GET_SERVER_FINISHED),	"GET_SERVER_FINISHED"},
 {ERR_FUNC(SSL_F_GET_SERVER_HELLO),	"GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_GET_SERVER_VERIFY),	"GET_SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_I2D_SSL_SESSION),	"i2d_SSL_SESSION"},
 {ERR_FUNC(SSL_F_READ_N),	"READ_N"},
 {ERR_FUNC(SSL_F_REQUEST_CERTIFICATE),	"REQUEST_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SERVER_FINISH),	"SERVER_FINISH"},
 {ERR_FUNC(SSL_F_SERVER_HELLO),	"SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SERVER_VERIFY),	"SERVER_VERIFY"},
 {ERR_FUNC(SSL_F_SSL23_ACCEPT),	"SSL23_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO),	"SSL23_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_CONNECT),	"SSL23_CONNECT"},
 {ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO),	"SSL23_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO),	"SSL23_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL23_PEEK),	"SSL23_PEEK"},
 {ERR_FUNC(SSL_F_SSL23_READ),	"SSL23_READ"},
 {ERR_FUNC(SSL_F_SSL23_WRITE),	"SSL23_WRITE"},
 {ERR_FUNC(SSL_F_SSL2_ACCEPT),	"SSL2_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL2_CONNECT),	"SSL2_CONNECT"},
 {ERR_FUNC(SSL_F_SSL2_ENC_INIT),	"SSL2_ENC_INIT"},
 {ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL),	"SSL2_GENERATE_KEY_MATERIAL"},
 {ERR_FUNC(SSL_F_SSL2_PEEK),	"SSL2_PEEK"},
 {ERR_FUNC(SSL_F_SSL2_READ),	"SSL2_READ"},
 {ERR_FUNC(SSL_F_SSL2_READ_INTERNAL),	"SSL2_READ_INTERNAL"},
 {ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE),	"SSL2_SET_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL2_WRITE),	"SSL2_WRITE"},
 {ERR_FUNC(SSL_F_SSL3_ACCEPT),	"SSL3_ACCEPT"},
 {ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF),	"SSL3_ADD_CERT_TO_BUF"},
 {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),	"SSL3_CALLBACK_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),	"SSL3_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),	"SSL3_CHECK_CERT_AND_ALGORITHM"},
 {ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO),	"SSL3_CHECK_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),	"SSL3_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"},
 {ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"},
 {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"},
 {ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"},
 {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS),	"SSL3_GET_CERT_STATUS"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY),	"SSL3_GET_CERT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),	"SSL3_GET_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),	"SSL3_GET_CLIENT_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE),	"SSL3_GET_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_FINISHED),	"SSL3_GET_FINISHED"},
 {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),	"SSL3_GET_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),	"SSL3_GET_MESSAGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),	"SSL3_GET_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_GET_RECORD),	"SSL3_GET_RECORD"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),	"SSL3_GET_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE),	"SSL3_GET_SERVER_DONE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),	"SSL3_GET_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),	"SSL3_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),	"SSL3_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL3_PEEK),	"SSL3_PEEK"},
 {ERR_FUNC(SSL_F_SSL3_READ_BYTES),	"SSL3_READ_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_READ_N),	"SSL3_READ_N"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST),	"SSL3_SEND_CERTIFICATE_REQUEST"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE),	"SSL3_SEND_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY),	"SSL3_SEND_CLIENT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE),	"SSL3_SEND_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO),	"SSL3_SEND_SERVER_HELLO"},
 {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE),	"SSL3_SEND_SERVER_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_BUFFERS),	"SSL3_SETUP_BUFFERS"},
 {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK),	"SSL3_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),	"SSL_add_dir_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),	"SSL_add_file_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"SSL_ADD_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"SSL_BAD_METHOD"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"SSL_BYTES_TO_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CERT_DUP),	"SSL_CERT_DUP"},
 {ERR_FUNC(SSL_F_SSL_CERT_INST),	"SSL_CERT_INST"},
 {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"},
 {ERR_FUNC(SSL_F_SSL_CERT_NEW),	"SSL_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),	"SSL_CIPHER_PROCESS_RULESTR"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),	"SSL_CIPHER_STRENGTH_SORT"},
 {ERR_FUNC(SSL_F_SSL_CLEAR),	"SSL_clear"},
 {ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),	"SSL_COMP_add_compression_method"},
 {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST),	"SSL_CREATE_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
 {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
 {ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
 {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
 {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY),	"SSL_GET_SERVER_SEND_PKEY"},
 {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
 {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
 {ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP),		"ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_SET_CERT),	"SSL_SET_CERT"},
 {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),	"SSL_set_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_SET_FD),	"SSL_set_fd"},
 {ERR_FUNC(SSL_F_SSL_SET_PKEY),	"SSL_SET_PKEY"},
 {ERR_FUNC(SSL_F_SSL_SET_PURPOSE),	"SSL_set_purpose"},
 {ERR_FUNC(SSL_F_SSL_SET_RFD),	"SSL_set_rfd"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION),	"SSL_set_session"},
 {ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),	"SSL_set_session_id_context"},
 {ERR_FUNC(SSL_F_SSL_SET_TRUST),	"SSL_set_trust"},
 {ERR_FUNC(SSL_F_SSL_SET_WFD),	"SSL_set_wfd"},
 {ERR_FUNC(SSL_F_SSL_SHUTDOWN),	"SSL_shutdown"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION),	"SSL_UNDEFINED_CONST_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION),	"SSL_UNDEFINED_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),	"SSL_UNDEFINED_VOID_FUNCTION"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE),	"SSL_use_certificate"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1),	"SSL_use_certificate_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE),	"SSL_use_certificate_file"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),	"SSL_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),	"SSL_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),	"SSL_use_PrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),	"SSL_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),	"SSL_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"SSL_VERIFY_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"},
 {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"},
 {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
 {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
 {0,NULL}
 	};
 
 static ERR_STRING_DATA SSL_str_reasons[]=
 	{
 {ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"},
 {ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"},
 {ERR_REASON(SSL_R_BAD_ALERT_RECORD)      ,"bad alert record"},
 {ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"},
 {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"},
 {ERR_REASON(SSL_R_BAD_CHECKSUM)          ,"bad checksum"},
 {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),"bad data returned by callback"},
 {ERR_REASON(SSL_R_BAD_DECOMPRESSION)     ,"bad decompression"},
 {ERR_REASON(SSL_R_BAD_DH_G_LENGTH)       ,"bad dh g length"},
 {ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) ,"bad dh pub key length"},
 {ERR_REASON(SSL_R_BAD_DH_P_LENGTH)       ,"bad dh p length"},
 {ERR_REASON(SSL_R_BAD_DIGEST_LENGTH)     ,"bad digest length"},
 {ERR_REASON(SSL_R_BAD_DSA_SIGNATURE)     ,"bad dsa signature"},
 {ERR_REASON(SSL_R_BAD_ECC_CERT)          ,"bad ecc cert"},
 {ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE)   ,"bad ecdsa signature"},
 {ERR_REASON(SSL_R_BAD_ECPOINT)           ,"bad ecpoint"},
 {ERR_REASON(SSL_R_BAD_HELLO_REQUEST)     ,"bad hello request"},
 {ERR_REASON(SSL_R_BAD_LENGTH)            ,"bad length"},
 {ERR_REASON(SSL_R_BAD_MAC_DECODE)        ,"bad mac decode"},
 {ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"},
 {ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"},
 {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"},
 {ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"},
 {ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_E_LENGTH)      ,"bad rsa e length"},
 {ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH),"bad rsa modulus length"},
 {ERR_REASON(SSL_R_BAD_RSA_SIGNATURE)     ,"bad rsa signature"},
 {ERR_REASON(SSL_R_BAD_SIGNATURE)         ,"bad signature"},
 {ERR_REASON(SSL_R_BAD_SSL_FILETYPE)      ,"bad ssl filetype"},
 {ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH),"bad ssl session id length"},
 {ERR_REASON(SSL_R_BAD_STATE)             ,"bad state"},
 {ERR_REASON(SSL_R_BAD_WRITE_RETRY)       ,"bad write retry"},
 {ERR_REASON(SSL_R_BIO_NOT_SET)           ,"bio not set"},
 {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),"block cipher pad is wrong"},
 {ERR_REASON(SSL_R_BN_LIB)                ,"bn lib"},
 {ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) ,"ca dn length mismatch"},
 {ERR_REASON(SSL_R_CA_DN_TOO_LONG)        ,"ca dn too long"},
 {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY)    ,"ccs received early"},
 {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"},
 {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH)  ,"cert length mismatch"},
 {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"},
 {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
 {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
 {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
 {ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"},
 {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
 {ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"},
 {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
 {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),"compression library error"},
 {ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT),"connection id is different"},
 {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET),"connection type not set"},
 {ERR_REASON(SSL_R_COOKIE_MISMATCH)       ,"cookie mismatch"},
 {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),"data between ccs and finished"},
 {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG)  ,"data length too long"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED)     ,"decryption failed"},
 {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"},
 {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"},
 {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED)   ,"digest check failed"},
 {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG)  ,"dtls message too big"},
 {ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID),"duplicate compression id"},
 {ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER),"ecgroup too large for cipher"},
 {ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),"encrypted length too long"},
 {ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY),"error generating tmp rsa key"},
 {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),"error in received cipher list"},
 {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"},
 {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"},
 {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"},
 {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"},
 {ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"},
 {ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"},
 {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK),"inappropriate fallback"},
 {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
 {ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"},
 {ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"},
 {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"},
 {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"},
 {ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"},
 {ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"},
 {ERR_REASON(SSL_R_KRB5)                  ,"krb5"},
 {ERR_REASON(SSL_R_KRB5_C_CC_PRINC)       ,"krb5 client cc principal (no tkt?)"},
 {ERR_REASON(SSL_R_KRB5_C_GET_CRED)       ,"krb5 client get cred"},
 {ERR_REASON(SSL_R_KRB5_C_INIT)           ,"krb5 client init"},
 {ERR_REASON(SSL_R_KRB5_C_MK_REQ)         ,"krb5 client mk_req (expired tkt?)"},
 {ERR_REASON(SSL_R_KRB5_S_BAD_TICKET)     ,"krb5 server bad ticket"},
 {ERR_REASON(SSL_R_KRB5_S_INIT)           ,"krb5 server init"},
 {ERR_REASON(SSL_R_KRB5_S_RD_REQ)         ,"krb5 server rd_req (keytab perms?)"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED)    ,"krb5 server tkt expired"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_NYV)        ,"krb5 server tkt not yet valid"},
 {ERR_REASON(SSL_R_KRB5_S_TKT_SKEW)       ,"krb5 server tkt skew"},
 {ERR_REASON(SSL_R_LENGTH_MISMATCH)       ,"length mismatch"},
 {ERR_REASON(SSL_R_LENGTH_TOO_SHORT)      ,"length too short"},
 {ERR_REASON(SSL_R_LIBRARY_BUG)           ,"library bug"},
 {ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS),"library has no ciphers"},
 {ERR_REASON(SSL_R_MESSAGE_TOO_LONG)      ,"message too long"},
 {ERR_REASON(SSL_R_MISSING_DH_DSA_CERT)   ,"missing dh dsa cert"},
 {ERR_REASON(SSL_R_MISSING_DH_KEY)        ,"missing dh key"},
 {ERR_REASON(SSL_R_MISSING_DH_RSA_CERT)   ,"missing dh rsa cert"},
 {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT),"missing dsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY),"missing export tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY),"missing export tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE),"missing rsa certificate"},
 {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),"missing rsa encrypting cert"},
 {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT),"missing rsa signing cert"},
 {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY)    ,"missing tmp dh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY)  ,"missing tmp ecdh key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"},
 {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"},
 {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"},
 {ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"},
 {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"},
 {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED),"no certificate returned"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SET)    ,"no certificate set"},
 {ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED),"no certificate specified"},
 {ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE)  ,"no ciphers available"},
 {ERR_REASON(SSL_R_NO_CIPHERS_PASSED)     ,"no ciphers passed"},
 {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"},
 {ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"},
 {ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"},
 {ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"},
 {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"},
 {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"},
 {ERR_REASON(SSL_R_NO_PRIVATEKEY)         ,"no privatekey"},
 {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"},
 {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"},
 {ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"},
 {ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
 {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
 {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
 {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
 {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
 {ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"},
 {ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"},
 {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"},
 {ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE),"peer error certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE),"peer error no certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER)  ,"peer error no cipher"},
 {ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE),"peer error unsupported certificate type"},
 {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"},
 {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"},
 {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
 {ERR_REASON(SSL_R_READ_BIO_NOT_SET)      ,"read bio not set"},
 {ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED)  ,"read timeout expired"},
 {ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE),"read wrong packet type"},
 {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"},
 {ERR_REASON(SSL_R_RECORD_TOO_LARGE)      ,"record too large"},
 {ERR_REASON(SSL_R_RECORD_TOO_SMALL)      ,"record too small"},
 {ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"},
 {ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"},
 {ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"},
 {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"},
 {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
 {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
 {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
 {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
 {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
 {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
 {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
 {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
 {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
 {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
 {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),"sslv3 alert bad record mac"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),"sslv3 alert certificate expired"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),"sslv3 alert certificate revoked"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),"sslv3 alert certificate unknown"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),"sslv3 alert decompression failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),"sslv3 alert handshake failure"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),"sslv3 alert illegal parameter"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),"sslv3 alert no certificate"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),"sslv3 alert unexpected message"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),"sslv3 alert unsupported certificate"},
 {ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),"ssl ctx has no default ssl version"},
 {ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) ,"ssl handshake failure"},
 {ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),"ssl library has no ciphers"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),"ssl session id callback failed"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT),"ssl session id conflict"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),"ssl session id context too long"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),"ssl session id has bad length"},
 {ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT),"ssl session id is different"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),"tlsv1 alert access denied"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR),"tlsv1 alert decode error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),"tlsv1 alert inappropriate fallback"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),"tlsv1 alert protocol version"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"},
 {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"},
 {ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"},
 {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
 {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
 {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
 {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
 {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"},
 {ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY),"unable to extract public key"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS),"unable to find dh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),"unable to find ecdh parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),"unable to find public key parameters"},
 {ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD),"unable to find ssl method"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES),"unable to load ssl2 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),"unable to load ssl3 md5 routines"},
 {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),"unable to load ssl3 sha1 routines"},
 {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE)    ,"unexpected message"},
 {ERR_REASON(SSL_R_UNEXPECTED_RECORD)     ,"unexpected record"},
 {ERR_REASON(SSL_R_UNINITIALIZED)         ,"uninitialized"},
 {ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE)    ,"unknown alert type"},
 {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"},
 {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"},
 {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"},
 {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"},
 {ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"},
 {ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION)   ,"unknown ssl version"},
 {ERR_REASON(SSL_R_UNKNOWN_STATE)         ,"unknown state"},
 {ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"},
 {ERR_REASON(SSL_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
 {ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
 {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"},
 {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"},
 {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"},
 {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
 {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
 {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
 {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
 {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"},
 {ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"},
 {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
 {ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
 {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
 {0,NULL}
 	};
 
 #endif
 
 void ERR_load_SSL_strings(void)
 	{
 #ifndef OPENSSL_NO_ERR
 
 	if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
 		{
 		ERR_load_strings(0,SSL_str_functs);
 		ERR_load_strings(0,SSL_str_reasons);
 		}
 #endif
 	}
Index: releng/9.3/crypto/openssl/ssl/ssl_locl.h
===================================================================
--- releng/9.3/crypto/openssl/ssl/ssl_locl.h	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/ssl_locl.h	(revision 284295)
@@ -1,1044 +1,1045 @@
 /* ssl/ssl_locl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer. 
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
  *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  *    permission of the OpenSSL Project.
  *
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com).
  *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
 #ifndef HEADER_SSL_LOCL_H
 #define HEADER_SSL_LOCL_H
 #include 
 #include 
 #include 
 #include 
 
 #include "e_os.h"
 
 #include 
 #ifndef OPENSSL_NO_COMP
 #include 
 #endif
 #include 
 #include 
 #ifndef OPENSSL_NO_RSA
 #include 
 #endif
 #ifndef OPENSSL_NO_DSA
 #include 
 #endif
 #include 
 #include 
 #include 
 
 #ifdef OPENSSL_BUILD_SHLIBSSL
 # undef OPENSSL_EXTERN
 # define OPENSSL_EXTERN OPENSSL_EXPORT
 #endif
 
 #define PKCS1_CHECK
 
 #define c2l(c,l)	(l = ((unsigned long)(*((c)++)))     , \
 			 l|=(((unsigned long)(*((c)++)))<< 8), \
 			 l|=(((unsigned long)(*((c)++)))<<16), \
 			 l|=(((unsigned long)(*((c)++)))<<24))
 
 /* NOTE - c is not incremented as per c2l */
 #define c2ln(c,l1,l2,n)	{ \
 			c+=n; \
 			l1=l2=0; \
 			switch (n) { \
 			case 8: l2 =((unsigned long)(*(--(c))))<<24; \
 			case 7: l2|=((unsigned long)(*(--(c))))<<16; \
 			case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
 			case 5: l2|=((unsigned long)(*(--(c))));     \
 			case 4: l1 =((unsigned long)(*(--(c))))<<24; \
 			case 3: l1|=((unsigned long)(*(--(c))))<<16; \
 			case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
 			case 1: l1|=((unsigned long)(*(--(c))));     \
 				} \
 			}
 
 #define l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff))
 
 #define n2l(c,l)	(l =((unsigned long)(*((c)++)))<<24, \
 			 l|=((unsigned long)(*((c)++)))<<16, \
 			 l|=((unsigned long)(*((c)++)))<< 8, \
 			 l|=((unsigned long)(*((c)++))))
 
 #define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n6(l,c)	(*((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define l2n8(l,c)	(*((c)++)=(unsigned char)(((l)>>56)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>48)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>40)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
 			 *((c)++)=(unsigned char)(((l)    )&0xff))
 
 #define n2l6(c,l)	(l =((BN_ULLONG)(*((c)++)))<<40, \
 			 l|=((BN_ULLONG)(*((c)++)))<<32, \
 			 l|=((BN_ULLONG)(*((c)++)))<<24, \
 			 l|=((BN_ULLONG)(*((c)++)))<<16, \
 			 l|=((BN_ULLONG)(*((c)++)))<< 8, \
 			 l|=((BN_ULLONG)(*((c)++))))
 
 /* NOTE - c is not incremented as per l2c */
 #define l2cn(l1,l2,c,n)	{ \
 			c+=n; \
 			switch (n) { \
 			case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
 			case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
 			case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
 			case 5: *(--(c))=(unsigned char)(((l2)    )&0xff); \
 			case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
 			case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
 			case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
 			case 1: *(--(c))=(unsigned char)(((l1)    )&0xff); \
 				} \
 			}
 
 #define n2s(c,s)	((s=(((unsigned int)(c[0]))<< 8)| \
 			    (((unsigned int)(c[1]))    )),c+=2)
 #define s2n(s,c)	((c[0]=(unsigned char)(((s)>> 8)&0xff), \
 			  c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
 
 #define n2l3(c,l)	((l =(((unsigned long)(c[0]))<<16)| \
 			     (((unsigned long)(c[1]))<< 8)| \
 			     (((unsigned long)(c[2]))    )),c+=3)
 
 #define l2n3(l,c)	((c[0]=(unsigned char)(((l)>>16)&0xff), \
 			  c[1]=(unsigned char)(((l)>> 8)&0xff), \
 			  c[2]=(unsigned char)(((l)    )&0xff)),c+=3)
 
 /* LOCAL STUFF */
 
 #define SSL_DECRYPT	0
 #define SSL_ENCRYPT	1
 
 #define TWO_BYTE_BIT	0x80
 #define SEC_ESC_BIT	0x40
 #define TWO_BYTE_MASK	0x7fff
 #define THREE_BYTE_MASK	0x3fff
 
 #define INC32(a)	((a)=((a)+1)&0xffffffffL)
 #define DEC32(a)	((a)=((a)-1)&0xffffffffL)
 #define MAX_MAC_SIZE	20 /* up from 16 for SSLv3 */
 
 /*
  * Define the Bitmasks for SSL_CIPHER.algorithms.
  * This bits are used packed as dense as possible. If new methods/ciphers
  * etc will be added, the bits a likely to change, so this information
  * is for internal library use only, even though SSL_CIPHER.algorithms
  * can be publicly accessed.
  * Use the according functions for cipher management instead.
  *
  * The bit mask handling in the selection and sorting scheme in
  * ssl_create_cipher_list() has only limited capabilities, reflecting
  * that the different entities within are mutually exclusive:
  * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
  */
 #define SSL_MKEY_MASK		0x000000FFL
 #define SSL_kRSA		0x00000001L /* RSA key exchange */
 #define SSL_kDHr		0x00000002L /* DH cert RSA CA cert */
 #define SSL_kDHd		0x00000004L /* DH cert DSA CA cert */
 #define SSL_kFZA		0x00000008L
 #define SSL_kEDH		0x00000010L /* tmp DH key no DH cert */
 #define SSL_kKRB5		0x00000020L /* Kerberos5 key exchange */
 #define SSL_kECDH               0x00000040L /* ECDH w/ long-term keys */
 #define SSL_kECDHE              0x00000080L /* ephemeral ECDH */
 #define SSL_EDH			(SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL))
 
 #define SSL_AUTH_MASK		0x00007F00L
 #define SSL_aRSA		0x00000100L /* Authenticate with RSA */
 #define SSL_aDSS 		0x00000200L /* Authenticate with DSS */
 #define SSL_DSS 		SSL_aDSS
 #define SSL_aFZA 		0x00000400L
 #define SSL_aNULL 		0x00000800L /* no Authenticate, ADH */
 #define SSL_aDH 		0x00001000L /* no Authenticate, ADH */
 #define SSL_aKRB5               0x00002000L /* Authenticate with KRB5 */
 #define SSL_aECDSA              0x00004000L /* Authenticate with ECDSA */
 
 #define SSL_NULL		(SSL_eNULL)
 #define SSL_ADH			(SSL_kEDH|SSL_aNULL)
 #define SSL_RSA			(SSL_kRSA|SSL_aRSA)
 #define SSL_DH			(SSL_kDHr|SSL_kDHd|SSL_kEDH)
 #define SSL_ECDH		(SSL_kECDH|SSL_kECDHE)
 #define SSL_FZA			(SSL_aFZA|SSL_kFZA|SSL_eFZA)
 #define SSL_KRB5                (SSL_kKRB5|SSL_aKRB5)
 
 #define SSL_ENC_MASK		0x1C3F8000L
 #define SSL_DES			0x00008000L
 #define SSL_3DES		0x00010000L
 #define SSL_RC4			0x00020000L
 #define SSL_RC2			0x00040000L
 #define SSL_IDEA		0x00080000L
 #define SSL_eFZA		0x00100000L
 #define SSL_eNULL		0x00200000L
 #define SSL_AES			0x04000000L
 #define SSL_CAMELLIA		0x08000000L
 #define SSL_SEED          	0x10000000L
 
 #define SSL_MAC_MASK		0x00c00000L
 #define SSL_MD5			0x00400000L
 #define SSL_SHA1		0x00800000L
 #define SSL_SHA			(SSL_SHA1)
 
 #define SSL_SSL_MASK		0x03000000L
 #define SSL_SSLV2		0x01000000L
 #define SSL_SSLV3		0x02000000L
 #define SSL_TLSV1		SSL_SSLV3	/* for now */
 
 /* we have used 1fffffff - 3 bits left to go. */
 
 /*
  * Export and cipher strength information. For each cipher we have to decide
  * whether it is exportable or not. This information is likely to change
  * over time, since the export control rules are no static technical issue.
  *
  * Independent of the export flag the cipher strength is sorted into classes.
  * SSL_EXP40 was denoting the 40bit US export limit of past times, which now
  * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change
  * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more,
  * since SSL_EXP64 could be similar to SSL_LOW.
  * For this reason SSL_MICRO and SSL_MINI macros are included to widen the
  * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed
  * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would
  * be possible.
  */
 #define SSL_EXP_MASK		0x00000003L
 #define SSL_NOT_EXP		0x00000001L
 #define SSL_EXPORT		0x00000002L
 
 #define SSL_STRONG_MASK		0x000000fcL
 #define SSL_STRONG_NONE		0x00000004L
 #define SSL_EXP40		0x00000008L
 #define SSL_MICRO		(SSL_EXP40)
 #define SSL_EXP56		0x00000010L
 #define SSL_MINI		(SSL_EXP56)
 #define SSL_LOW			0x00000020L
 #define SSL_MEDIUM		0x00000040L
 #define SSL_HIGH		0x00000080L
 #define SSL_FIPS		0x00000100L
 
 /* we have used 000001ff - 23 bits left to go */
 
 /*
  * Macros to check the export status and cipher strength for export ciphers.
  * Even though the macros for EXPORT and EXPORT40/56 have similar names,
  * their meaning is different:
  * *_EXPORT macros check the 'exportable' status.
  * *_EXPORT40/56 macros are used to check whether a certain cipher strength
  *          is given.
  * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct
  * algorithm structure element to be passed (algorithms, algo_strength) and no
  * typechecking can be done as they are all of type unsigned long, their
  * direct usage is discouraged.
  * Use the SSL_C_* macros instead.
  */
 #define SSL_IS_EXPORT(a)	((a)&SSL_EXPORT)
 #define SSL_IS_EXPORT56(a)	((a)&SSL_EXP56)
 #define SSL_IS_EXPORT40(a)	((a)&SSL_EXP40)
 #define SSL_C_IS_EXPORT(c)	SSL_IS_EXPORT((c)->algo_strength)
 #define SSL_C_IS_EXPORT56(c)	SSL_IS_EXPORT56((c)->algo_strength)
 #define SSL_C_IS_EXPORT40(c)	SSL_IS_EXPORT40((c)->algo_strength)
 
 #define SSL_EXPORT_KEYLENGTH(a,s)	(SSL_IS_EXPORT40(s) ? 5 : \
 				 ((a)&SSL_ENC_MASK) == SSL_DES ? 8 : 7)
 #define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024)
 #define SSL_C_EXPORT_KEYLENGTH(c)	SSL_EXPORT_KEYLENGTH((c)->algorithms, \
 				(c)->algo_strength)
 #define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
 
 
 #define SSL_ALL			0xffffffffL
 #define SSL_ALL_CIPHERS		(SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|\
 				SSL_MAC_MASK)
 #define SSL_ALL_STRENGTHS	(SSL_EXP_MASK|SSL_STRONG_MASK)
 
 /* Mostly for SSLv3 */
 #define SSL_PKEY_RSA_ENC	0
 #define SSL_PKEY_RSA_SIGN	1
 #define SSL_PKEY_DSA_SIGN	2
 #define SSL_PKEY_DH_RSA		3
 #define SSL_PKEY_DH_DSA		4
 #define SSL_PKEY_ECC            5
 #define SSL_PKEY_NUM		6
 
 /* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) |
  * 	    <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN)
  * SSL_kDH  <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
  * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN
  * SSL_aRSA <- RSA_ENC | RSA_SIGN
  * SSL_aDSS <- DSA_SIGN
  */
 
 /*
 #define CERT_INVALID		0
 #define CERT_PUBLIC_KEY		1
 #define CERT_PRIVATE_KEY	2
 */
 
 #ifndef OPENSSL_NO_EC
 /* From ECC-TLS draft, used in encoding the curve type in 
  * ECParameters
  */
 #define EXPLICIT_PRIME_CURVE_TYPE  1   
 #define EXPLICIT_CHAR2_CURVE_TYPE  2
 #define NAMED_CURVE_TYPE           3
 #endif  /* OPENSSL_NO_EC */
 
 typedef struct cert_pkey_st
 	{
 	X509 *x509;
 	EVP_PKEY *privatekey;
 	} CERT_PKEY;
 
 typedef struct cert_st
 	{
 	/* Current active set */
 	CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
 			 * Probably it would make more sense to store
 			 * an index, not a pointer. */
  
 	/* The following masks are for the key and auth
 	 * algorithms that are supported by the certs below */
 	int valid;
 	unsigned long mask;
 	unsigned long export_mask;
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa_tmp;
 	RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *dh_tmp;
 	DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *ecdh_tmp;
 	/* Callback for generating ephemeral ECDH keys */
 	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
 #endif
 
 	CERT_PKEY pkeys[SSL_PKEY_NUM];
 
 	int references; /* >1 only if SSL_copy_session_id is used */
 	} CERT;
 
 
 typedef struct sess_cert_st
 	{
 	STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */
 
 	/* The 'peer_...' members are used only by clients. */
 	int peer_cert_type;
 
 	CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */
 	CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
 	/* Obviously we don't have the private keys of these,
 	 * so maybe we shouldn't even use the CERT_PKEY type here. */
 
 #ifndef OPENSSL_NO_RSA
 	RSA *peer_rsa_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_DH
 	DH *peer_dh_tmp; /* not used for SSL 2 */
 #endif
 #ifndef OPENSSL_NO_ECDH
 	EC_KEY *peer_ecdh_tmp;
 #endif
 
 	int references; /* actually always 1 at the moment */
 	} SESS_CERT;
 
 
 /*#define MAC_DEBUG	*/
 
 /*#define ERR_DEBUG	*/
 /*#define ABORT_DEBUG	*/
 /*#define PKT_DEBUG 1   */
 /*#define DES_DEBUG	*/
 /*#define DES_OFB_DEBUG	*/
 /*#define SSL_DEBUG	*/
 /*#define RSA_DEBUG	*/ 
 /*#define IDEA_DEBUG	*/ 
 
 #define FP_ICC  (int (*)(const void *,const void *))
 #define ssl_put_cipher_by_char(ssl,ciph,ptr) \
 		((ssl)->method->put_cipher_by_char((ciph),(ptr)))
 #define ssl_get_cipher_by_char(ssl,ptr) \
 		((ssl)->method->get_cipher_by_char(ptr))
 
 /* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff
  * It is a bit of a mess of functions, but hell, think of it as
  * an opaque structure :-) */
 typedef struct ssl3_enc_method
 	{
 	int (*enc)(SSL *, int);
 	int (*mac)(SSL *, unsigned char *, int);
 	int (*setup_key_block)(SSL *);
 	int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int);
 	int (*change_cipher_state)(SSL *, int);
 	int (*final_finish_mac)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char *, int, unsigned char *);
 	int finish_mac_length;
 	int (*cert_verify_mac)(SSL *, EVP_MD_CTX *, unsigned char *);
 	const char *client_finished_label;
 	int client_finished_label_len;
 	const char *server_finished_label;
 	int server_finished_label_len;
 	int (*alert_value)(int);
 	} SSL3_ENC_METHOD;
 
 #ifndef OPENSSL_NO_COMP
 /* Used for holding the relevant compression methods loaded into SSL_CTX */
 typedef struct ssl3_comp_st
 	{
 	int comp_id;	/* The identifier byte for this compression type */
 	char *name;	/* Text name used for the compression type */
 	COMP_METHOD *method; /* The method :-) */
 	} SSL3_COMP;
 #endif
 
 extern SSL3_ENC_METHOD ssl3_undef_enc_method;
 OPENSSL_EXTERN SSL_CIPHER ssl2_ciphers[];
 OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[];
 
 
 SSL_METHOD *ssl_bad_method(int ver);
 SSL_METHOD *sslv2_base_method(void);
 SSL_METHOD *sslv23_base_method(void);
 SSL_METHOD *sslv3_base_method(void);
 
 extern SSL3_ENC_METHOD TLSv1_enc_data;
 extern SSL3_ENC_METHOD SSLv3_enc_data;
 extern SSL3_ENC_METHOD DTLSv1_enc_data;
 
 #define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		TLS1_VERSION, \
 		tls1_new, \
 		tls1_clear, \
 		tls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		tls1_default_timeout, \
 		&TLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		SSL3_VERSION, \
 		ssl3_new, \
 		ssl3_clear, \
 		ssl3_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		ssl3_get_message, \
 		ssl3_read_bytes, \
 		ssl3_write_bytes, \
 		ssl3_dispatch_alert, \
 		ssl3_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		ssl3_get_cipher, \
 		s_get_meth, \
 		ssl3_default_timeout, \
 		&SSLv3_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 	TLS1_VERSION, \
 	tls1_new, \
 	tls1_clear, \
 	tls1_free, \
 	s_accept, \
 	s_connect, \
 	ssl23_read, \
 	ssl23_peek, \
 	ssl23_write, \
 	ssl_undefined_function, \
 	ssl_undefined_function, \
 	ssl_ok, \
 	ssl3_get_message, \
 	ssl3_read_bytes, \
 	ssl3_write_bytes, \
 	ssl3_dispatch_alert, \
 	ssl3_ctrl, \
 	ssl3_ctx_ctrl, \
 	ssl23_get_cipher_by_char, \
 	ssl23_put_cipher_by_char, \
 	ssl_undefined_const_function, \
 	ssl23_num_ciphers, \
 	ssl23_get_cipher, \
 	s_get_meth, \
 	ssl23_default_timeout, \
 	&ssl3_undef_enc_method, \
 	ssl_undefined_void_function, \
 	ssl3_callback_ctrl, \
 	ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_ssl2_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		SSL2_VERSION, \
 		ssl2_new,	/* local */ \
 		ssl2_clear,	/* local */ \
 		ssl2_free,	/* local */ \
 		s_accept, \
 		s_connect, \
 		ssl2_read, \
 		ssl2_peek, \
 		ssl2_write, \
 		ssl2_shutdown, \
 		ssl_ok,	/* NULL - renegotiate */ \
 		ssl_ok,	/* NULL - check renegotiate */ \
 		NULL, /* NULL - ssl_get_message */ \
 		NULL, /* NULL - ssl_get_record */ \
 		NULL, /* NULL - ssl_write_bytes */ \
 		NULL, /* NULL - dispatch_alert */ \
 		ssl2_ctrl,	/* local */ \
 		ssl2_ctx_ctrl,	/* local */ \
 		ssl2_get_cipher_by_char, \
 		ssl2_put_cipher_by_char, \
 		ssl2_pending, \
 		ssl2_num_ciphers, \
 		ssl2_get_cipher, \
 		s_get_meth, \
 		ssl2_default_timeout, \
 		&ssl3_undef_enc_method, \
 		ssl_undefined_void_function, \
 		ssl2_callback_ctrl,	/* local */ \
 		ssl2_ctx_callback_ctrl,	/* local */ \
 	}; \
 	return &func_name##_data; \
 	}
 
 #define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
 SSL_METHOD *func_name(void)  \
 	{ \
 	static SSL_METHOD func_name##_data= { \
 		DTLS1_VERSION, \
 		dtls1_new, \
 		dtls1_clear, \
 		dtls1_free, \
 		s_accept, \
 		s_connect, \
 		ssl3_read, \
 		ssl3_peek, \
 		ssl3_write, \
 		ssl3_shutdown, \
 		ssl3_renegotiate, \
 		ssl3_renegotiate_check, \
 		dtls1_get_message, \
 		dtls1_read_bytes, \
 		dtls1_write_app_data_bytes, \
 		dtls1_dispatch_alert, \
 		dtls1_ctrl, \
 		ssl3_ctx_ctrl, \
 		ssl3_get_cipher_by_char, \
 		ssl3_put_cipher_by_char, \
 		ssl3_pending, \
 		ssl3_num_ciphers, \
 		dtls1_get_cipher, \
 		s_get_meth, \
 		dtls1_default_timeout, \
 		&DTLSv1_enc_data, \
 		ssl_undefined_void_function, \
 		ssl3_callback_ctrl, \
 		ssl3_ctx_callback_ctrl, \
 	}; \
 	return &func_name##_data; \
 	}
 
 void ssl_clear_cipher_ctx(SSL *s);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
 int ssl_cert_inst(CERT **o);
 void ssl_cert_free(CERT *c);
 SESS_CERT *ssl_sess_cert_new(void);
 void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
 			const SSL_CIPHER * const *bp);
 STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
 					       STACK_OF(SSL_CIPHER) **skp);
 int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                              int (*put_cb)(const SSL_CIPHER *, unsigned char *));
 STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
 					     STACK_OF(SSL_CIPHER) **pref,
 					     STACK_OF(SSL_CIPHER) **sorted,
 					     const char *rule_str);
 void ssl_update_cache(SSL *s, int mode);
 int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
 		       const EVP_MD **md,SSL_COMP **comp);
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);
 CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
 X509 *ssl_get_server_send_cert(const SSL *);
 EVP_PKEY *ssl_get_sign_pkey(SSL *,SSL_CIPHER *);
 int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
 void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher);
 STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
 int ssl_verify_alarm_type(long type);
 void ssl_load_ciphers(void);
 
 int ssl2_enc_init(SSL *s, int client);
 int ssl2_generate_key_material(SSL *s);
 void ssl2_enc(SSL *s,int send_data);
 void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
 SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
 int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 int ssl2_part_read(SSL *s, unsigned long f, int i);
 int ssl2_do_write(SSL *s);
 int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
 void ssl2_return_error(SSL *s,int reason);
 void ssl2_write_error(SSL *s);
 int ssl2_num_ciphers(void);
 SSL_CIPHER *ssl2_get_cipher(unsigned int u);
 int	ssl2_new(SSL *s);
 void	ssl2_free(SSL *s);
 int	ssl2_accept(SSL *s);
 int	ssl2_connect(SSL *s);
 int	ssl2_read(SSL *s, void *buf, int len);
 int	ssl2_peek(SSL *s, void *buf, int len);
 int	ssl2_write(SSL *s, const void *buf, int len);
 int	ssl2_shutdown(SSL *s);
 void	ssl2_clear(SSL *s);
 long	ssl2_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl2_pending(const SSL *s);
 long	ssl2_default_timeout(void );
 
 SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
 int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 void ssl3_init_finished_mac(SSL *s);
 int ssl3_send_server_certificate(SSL *s);
 int ssl3_send_newsession_ticket(SSL *s);
 int ssl3_send_cert_status(SSL *s);
 int ssl3_get_finished(SSL *s,int state_a,int state_b);
 int ssl3_setup_key_block(SSL *s);
 int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
 int ssl3_change_cipher_state(SSL *s,int which);
 void ssl3_cleanup_key_block(SSL *s);
 int ssl3_do_write(SSL *s,int type);
 int ssl3_send_alert(SSL *s,int level, int desc);
 int ssl3_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int ssl3_get_req_cert_type(SSL *s,unsigned char *p);
 long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen);
 int ssl3_num_ciphers(void);
 SSL_CIPHER *ssl3_get_cipher(unsigned int u);
 int ssl3_renegotiate(SSL *ssl); 
 int ssl3_renegotiate_check(SSL *ssl); 
 int ssl3_dispatch_alert(SSL *s);
 int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
 int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1, EVP_MD_CTX *ctx2,
 	const char *sender, int slen,unsigned char *p);
 int ssl3_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p);
 void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
 int ssl3_enc(SSL *s, int send_data);
 int ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
 unsigned long ssl3_output_cert_chain(SSL *s, X509 *x);
 SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt,
 			       STACK_OF(SSL_CIPHER) *srvr);
 int	ssl3_setup_buffers(SSL *s);
 int	ssl3_new(SSL *s);
 void	ssl3_free(SSL *s);
 int	ssl3_accept(SSL *s);
 int	ssl3_connect(SSL *s);
 int	ssl3_read(SSL *s, void *buf, int len);
 int	ssl3_peek(SSL *s, void *buf, int len);
 int	ssl3_write(SSL *s, const void *buf, int len);
 int	ssl3_shutdown(SSL *s);
 void	ssl3_clear(SSL *s);
 long	ssl3_ctrl(SSL *s,int cmd, long larg, void *parg);
 long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg);
 long	ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 long	ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
 int	ssl3_pending(const SSL *s);
 
 void ssl3_record_sequence_update(unsigned char *seq);
 int ssl3_do_change_cipher_spec(SSL *ssl);
 long ssl3_default_timeout(void );
 
 int ssl23_num_ciphers(void );
 SSL_CIPHER *ssl23_get_cipher(unsigned int u);
 int ssl23_read(SSL *s, void *buf, int len);
 int ssl23_peek(SSL *s, void *buf, int len);
 int ssl23_write(SSL *s, const void *buf, int len);
 int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
 SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p);
 long ssl23_default_timeout(void );
 
 long tls1_default_timeout(void);
 int dtls1_do_write(SSL *s,int type);
 int ssl3_read_n(SSL *s, int n, int max, int extend);
 int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
 int ssl3_do_compress(SSL *ssl);
 int ssl3_do_uncompress(SSL *ssl);
 int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
 	unsigned int len);
 unsigned char *dtls1_set_message_header(SSL *s, 
 	unsigned char *p, unsigned char mt,	unsigned long len, 
 	unsigned long frag_off, unsigned long frag_len);
 
 int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
 int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
 
 int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
 int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
 unsigned long dtls1_output_cert_chain(SSL *s, X509 *x);
 int dtls1_read_failed(SSL *s, int code);
 int dtls1_buffer_message(SSL *s, int ccs);
 int dtls1_retransmit_message(SSL *s, unsigned short seq, 
 	unsigned long frag_off, int *found);
 int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
 int dtls1_retransmit_buffered_messages(SSL *s);
 void dtls1_clear_record_buffer(SSL *s);
 void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
 void dtls1_reset_seq_numbers(SSL *s, int rw);
 long dtls1_default_timeout(void);
 struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
 int dtls1_check_timeout_num(SSL *s);
 int dtls1_handle_timeout(SSL *s);
 SSL_CIPHER *dtls1_get_cipher(unsigned int u);
 void dtls1_start_timer(SSL *s);
 void dtls1_stop_timer(SSL *s);
 int dtls1_is_timer_expired(SSL *s);
 void dtls1_double_timeout(SSL *s);
 int dtls1_send_newsession_ticket(SSL *s);
 unsigned int dtls1_min_mtu(void);
 
 
 /* some client-only functions */
 int ssl3_client_hello(SSL *s);
 int ssl3_get_server_hello(SSL *s);
 int ssl3_get_certificate_request(SSL *s);
 int ssl3_get_new_session_ticket(SSL *s);
 int ssl3_get_cert_status(SSL *s);
 int ssl3_get_server_done(SSL *s);
 int ssl3_send_client_verify(SSL *s);
 int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
 int ssl3_send_client_certificate(SSL *s);
 int ssl3_send_client_key_exchange(SSL *s);
 int ssl3_get_key_exchange(SSL *s);
 int ssl3_get_server_certificate(SSL *s);
 int ssl3_check_cert_and_algorithm(SSL *s);
 #ifndef OPENSSL_NO_TLSEXT
 int ssl3_check_finished(SSL *s);
 #endif
 
 int dtls1_client_hello(SSL *s);
 int dtls1_send_client_certificate(SSL *s);
 int dtls1_send_client_key_exchange(SSL *s);
 int dtls1_send_client_verify(SSL *s);
 
 /* some server-only functions */
 int ssl3_get_client_hello(SSL *s);
 int ssl3_send_server_hello(SSL *s);
 int ssl3_send_hello_request(SSL *s);
 int ssl3_send_server_key_exchange(SSL *s);
 int ssl3_send_certificate_request(SSL *s);
 int ssl3_send_server_done(SSL *s);
 int ssl3_check_client_hello(SSL *s);
 int ssl3_get_client_certificate(SSL *s);
 int ssl3_get_client_key_exchange(SSL *s);
 int ssl3_get_cert_verify(SSL *s);
 
 int dtls1_send_hello_request(SSL *s);
 int dtls1_send_server_hello(SSL *s);
 int dtls1_send_server_certificate(SSL *s);
 int dtls1_send_server_key_exchange(SSL *s);
 int dtls1_send_certificate_request(SSL *s);
 int dtls1_send_server_done(SSL *s);
 
 
 
 int ssl23_accept(SSL *s);
 int ssl23_connect(SSL *s);
 int ssl23_read_bytes(SSL *s, int n);
 int ssl23_write_bytes(SSL *s);
 
 int tls1_new(SSL *s);
 void tls1_free(SSL *s);
 void tls1_clear(SSL *s);
 long tls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
 SSL_METHOD *tlsv1_base_method(void );
 
 int dtls1_new(SSL *s);
 int	dtls1_accept(SSL *s);
 int	dtls1_connect(SSL *s);
 void dtls1_free(SSL *s);
 void dtls1_clear(SSL *s);
 long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
 SSL_METHOD *dtlsv1_base_method(void );
 
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
 int dtls1_get_record(SSL *s);
 int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
 	unsigned int len, int create_empty_fragement);
 int dtls1_dispatch_alert(SSL *s);
 int dtls1_enc(SSL *s, int snd);
 
 int ssl_init_wbio_buffer(SSL *s, int push);
 void ssl_free_wbio_buffer(SSL *s);
 
 int tls1_change_cipher_state(SSL *s, int which);
 int tls1_setup_key_block(SSL *s);
 int tls1_enc(SSL *s, int snd);
 int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx,
 	const char *str, int slen, unsigned char *p);
 int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p);
 int tls1_mac(SSL *ssl, unsigned char *md, int snd);
 int tls1_generate_master_secret(SSL *s, unsigned char *out,
 	unsigned char *p, int len);
 int tls1_alert_code(int code);
 int ssl3_alert_code(int code);
 int ssl_ok(SSL *s);
 
 int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
 
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
 
 #ifndef OPENSSL_NO_TLSEXT
 unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
 int ssl_prepare_clienthello_tlsext(SSL *s);
 int ssl_prepare_serverhello_tlsext(SSL *s);
 int ssl_check_clienthello_tlsext_early(SSL *s);
 int ssl_check_clienthello_tlsext_late(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
 
 #ifdef OPENSSL_NO_SHA256
 #define tlsext_tick_md	EVP_sha1
 #else
 #define tlsext_tick_md	EVP_sha256
 #endif
 int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 				const unsigned char *limit, SSL_SESSION **ret);
 EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 
 int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 					int maxlen);
 int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 					  int *al);
 #endif
 /* s3_cbc.c */
 void ssl3_cbc_copy_mac(unsigned char* out,
 		       const SSL3_RECORD *rec,
 		       unsigned md_size,unsigned orig_len);
 int ssl3_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 int tls1_cbc_remove_padding(const SSL* s,
 			    SSL3_RECORD *rec,
 			    unsigned block_size,
 			    unsigned mac_size);
 char ssl3_cbc_record_digest_supported(const EVP_MD *hash);
 void ssl3_cbc_digest_record(
 	const EVP_MD *hash,
 	unsigned char* md_out,
 	size_t* md_out_size,
 	const unsigned char header[13],
 	const unsigned char *data,
 	size_t data_plus_mac_size,
 	size_t data_plus_mac_plus_padding_size,
 	const unsigned char *mac_secret,
 	unsigned mac_secret_length,
 	char is_sslv3);
 
 void tls_fips_digest_extra(
 	const EVP_CIPHER_CTX *cipher_ctx, const EVP_MD *hash, HMAC_CTX *hctx,
 	const unsigned char *data, size_t data_len, size_t orig_len);
 
 #endif
Index: releng/9.3/crypto/openssl/ssl/ssl_sess.c
===================================================================
--- releng/9.3/crypto/openssl/ssl/ssl_sess.c	(revision 284294)
+++ releng/9.3/crypto/openssl/ssl/ssl_sess.c	(revision 284295)
@@ -1,911 +1,984 @@
 /* ssl/ssl_sess.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
  * 
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  * 
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    "This product includes cryptographic software written by
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
  * 4. If you include any Windows specific code (or a derivative thereof) from 
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  * 
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
 #include 
 #include 
 #include 
 #ifndef OPENSSL_NO_ENGINE
 #include 
 #endif
 #include "ssl_locl.h"
 
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
 
 SSL_SESSION *SSL_get_session(const SSL *ssl)
 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
 	{
 	return(ssl->session);
 	}
 
 SSL_SESSION *SSL_get1_session(SSL *ssl)
 /* variant of SSL_get_session: caller really gets something */
 	{
 	SSL_SESSION *sess;
 	/* Need to lock this all up rather than just use CRYPTO_add so that
 	 * somebody doesn't free ssl->session between when we check it's
 	 * non-null and when we up the reference count. */
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
 	sess = ssl->session;
 	if(sess)
 		sess->references++;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
 	return(sess);
 	}
 
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
 			new_func, dup_func, free_func);
 	}
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
 	{
 	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
 	}
 
 void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
 	{
 	return(CRYPTO_get_ex_data(&s->ex_data,idx));
 	}
 
 SSL_SESSION *SSL_SESSION_new(void)
 	{
 	SSL_SESSION *ss;
 
 	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
 	if (ss == NULL)
 		{
 		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
 		return(0);
 		}
 	memset(ss,0,sizeof(SSL_SESSION));
 
 	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
 	ss->references=1;
 	ss->timeout=60*5+4; /* 5 minute timeout by default */
 	ss->time=(unsigned long)time(NULL);
 	ss->prev=NULL;
 	ss->next=NULL;
 	ss->compress_meth=0;
 #ifndef OPENSSL_NO_TLSEXT
 	ss->tlsext_hostname = NULL; 
 #endif
 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 	return(ss);
 	}
 
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+    /*
+     * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+#endif
+    dest->tlsext_tick = NULL;
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)
 		*len = s->session_id_length;
 	return s->session_id;
 	}
 
 /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
  * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
  * until we have no conflict is going to complete in one iteration pretty much
  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  * and we still can't avoid a conflict - well that's a reasonable point to call
  * it quits. Either the RAND code is broken or someone is trying to open roughly
  * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
  * store that many sessions is perhaps a more interesting question ... */
 
 #define MAX_SESS_ID_ATTEMPTS 10
 static int def_generate_session_id(const SSL *ssl, unsigned char *id,
 				unsigned int *id_len)
 {
 	unsigned int retry = 0;
 	do
 		if (RAND_pseudo_bytes(id, *id_len) <= 0)
 			return 0;
 	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
 		(++retry < MAX_SESS_ID_ATTEMPTS));
 	if(retry < MAX_SESS_ID_ATTEMPTS)
 		return 1;
 	/* else - woops a session_id match */
 	/* XXX We should also check the external cache --
 	 * but the probability of a collision is negligible, and
 	 * we could not prevent the concurrent creation of sessions
 	 * with identical IDs since we currently don't have means
 	 * to atomically check whether a session ID already exists
 	 * and make a reservation for it if it does not
 	 * (this problem applies to the internal cache as well).
 	 */
 	return 0;
 }
 
 int ssl_get_new_session(SSL *s, int session)
 	{
 	/* This gets used by clients and servers. */
 
 	unsigned int tmp;
 	SSL_SESSION *ss=NULL;
 	GEN_SESSION_CB cb = def_generate_session_id;
 
 	if ((ss=SSL_SESSION_new()) == NULL) return(0);
 
 	/* If the context has a default timeout, use it */
 	if (s->ctx->session_timeout == 0)
 		ss->timeout=SSL_get_default_timeout(s);
 	else
 		ss->timeout=s->ctx->session_timeout;
 
 	if (s->session != NULL)
 		{
 		SSL_SESSION_free(s->session);
 		s->session=NULL;
 		}
 
 	if (session)
 		{
 		if (s->version == SSL2_VERSION)
 			{
 			ss->ssl_version=SSL2_VERSION;
 			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == SSL3_VERSION)
 			{
 			ss->ssl_version=SSL3_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == TLS1_VERSION)
 			{
 			ss->ssl_version=TLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_BAD_VER)
 			{
 			ss->ssl_version=DTLS1_BAD_VER;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else if (s->version == DTLS1_VERSION)
 			{
 			ss->ssl_version=DTLS1_VERSION;
 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
 			}
 		else
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		/* If RFC4507 ticket use empty session ID */
 		if (s->tlsext_ticket_expected)
 			{
 			ss->session_id_length = 0;
 			goto sess_id_done;
 			}
 #endif
 		/* Choose which callback will set the session ID */
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		if(s->generate_session_id)
 			cb = s->generate_session_id;
 		else if(s->ctx->generate_session_id)
 			cb = s->ctx->generate_session_id;
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		/* Choose a session ID */
 		tmp = ss->session_id_length;
 		if(!cb(s, ss->session_id, &tmp))
 			{
 			/* The callback failed */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* Don't allow the callback to set the session length to zero.
 		 * nor set it higher than it was. */
 		if(!tmp || (tmp > ss->session_id_length))
 			{
 			/* The callback set an illegal length */
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 		/* If the session length was shrunk and we're SSLv2, pad it */
 		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
 			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
 		else
 			ss->session_id_length = tmp;
 		/* Finally, check for a conflict */
 		if(SSL_has_matching_session_id(s, ss->session_id,
 						ss->session_id_length))
 			{
 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,
 				SSL_R_SSL_SESSION_ID_CONFLICT);
 			SSL_SESSION_free(ss);
 			return(0);
 			}
 #ifndef OPENSSL_NO_TLSEXT
 		sess_id_done:
 		if (s->tlsext_hostname) {
 			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
 			if (ss->tlsext_hostname == NULL) {
 				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 				SSL_SESSION_free(ss);
 				return 0;
 				}
 			}
 #endif
 		}
 	else
 		{
 		ss->session_id_length=0;
 		}
 
 	if (s->sid_ctx_length > sizeof ss->sid_ctx)
 		{
 		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
 		SSL_SESSION_free(ss);
 		return 0;
 		}
 	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
 	ss->sid_ctx_length=s->sid_ctx_length;
 	s->session=ss;
 	ss->ssl_version=s->version;
 	ss->verify_result = X509_V_OK;
 
 	return(1);
 	}
 
 int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
 			const unsigned char *limit)
 	{
 	/* This is used only by servers. */
 
 	SSL_SESSION *ret=NULL;
 	int fatal = 0;
 #ifndef OPENSSL_NO_TLSEXT
 	int r;
 #endif
   
 	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
 		goto err;
 #ifndef OPENSSL_NO_TLSEXT
  	r = tls1_process_ticket(s, session_id, len, limit, &ret);
 	if (r == -1)
 		{
 		fatal = 1;
  		goto err;
 		}
 	else if (r == 0 || (!ret && !len))
 		goto err;
 	else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 #else
 	if (len == 0)
 		goto err;
 	if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 #endif
 		{
 		SSL_SESSION data;
 		data.ssl_version=s->version;
 		data.session_id_length=len;
 		if (len == 0)
 			return 0;
  		memcpy(data.session_id,session_id,len);
 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 		ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
 		if (ret != NULL)
 		    /* don't allow other threads to steal it: */
 		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		}
 
 	if (ret == NULL)
 		{
 		int copy=1;
 	
 		s->ctx->stats.sess_miss++;
 		ret=NULL;
 		if (s->ctx->get_session_cb != NULL
 		    && (ret=s->ctx->get_session_cb(s,session_id,len,©))
 		       != NULL)
 			{
 			s->ctx->stats.sess_cb_hit++;
 
 			/* Increment reference count now if the session callback
 			 * asks us to do so (note that if the session structures
 			 * returned by the callback are shared between threads,
 			 * it must handle the reference count itself [i.e. copy == 0],
 			 * or things won't be thread-safe). */
 			if (copy)
 				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 
 			/* Add the externally cached session to the internal
 			 * cache as well if and only if we are supposed to. */
 			if(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
 				/* The following should not return 1, otherwise,
 				 * things are very strange */
 				SSL_CTX_add_session(s->ctx,ret);
 			}
 		if (ret == NULL)
 			goto err;
 		}
 
 	/* Now ret is non-NULL, and we own one of its reference counts. */
 
 	if (ret->sid_ctx_length != s->sid_ctx_length
 	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
 		{
 		/* We've found the session named by the client, but we don't
 		 * want to use it in this context. */
 
 #if 0 /* The client cannot always know when a session is not appropriate,
        * so we shouldn't generate an error message. */
 
 		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 #endif
 		goto err; /* treat like cache miss */
 		}
 	
 	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
 		{
 		/* We can't be sure if this session is being used out of
 		 * context, which is especially important for SSL_VERIFY_PEER.
 		 * The application should have used SSL[_CTX]_set_session_id_context.
 		 *
 		 * For this error case, we generate an error instead of treating
 		 * the event like a cache miss (otherwise it would be easy for
 		 * applications to effectively disable the session cache by
 		 * accident without anyone noticing).
 		 */
 		
 		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
 		fatal = 1;
 		goto err;
 		}
 
 	if (ret->cipher == NULL)
 		{
 		unsigned char buf[5],*p;
 		unsigned long l;
 
 		p=buf;
 		l=ret->cipher_id;
 		l2n(l,p);
 		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR)
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
 		else 
 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
 		if (ret->cipher == NULL)
 			goto err;
 		}
 
 
 #if 0 /* This is way too late. */
 
 	/* If a thread got the session, then 'swaped', and another got
 	 * it and then due to a time-out decided to 'OPENSSL_free' it we could
 	 * be in trouble.  So I'll increment it now, then double decrement
 	 * later - am I speaking rubbish?. */
 	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
 #endif
 
 	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
 		{
 		s->ctx->stats.sess_timeout++;
 		/* remove it from the cache */
 		SSL_CTX_remove_session(s->ctx,ret);
 		goto err;
 		}
 
 	s->ctx->stats.sess_hit++;
 
 	/* ret->time=time(NULL); */ /* rezero timeout? */
 	/* again, just leave the session 
 	 * if it is the same session, we have just incremented and
 	 * then decremented the reference count :-) */
 	if (s->session != NULL)
 		SSL_SESSION_free(s->session);
 	s->session=ret;
 	s->verify_result = s->session->verify_result;
 	return(1);
 
  err:
 	if (ret != NULL)
 		SSL_SESSION_free(ret);
 	if (fatal)
 		return -1;
 	else
 		return 0;
 	}
 
 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
 	{
 	int ret=0;
 	SSL_SESSION *s;
 
 	/* add just 1 reference count for the SSL_CTX's session cache
 	 * even though it has two ways of access: each session is in a
 	 * doubly linked list and an lhash */
 	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
 	/* if session c is in already in cache, we take back the increment later */
 
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	s=(SSL_SESSION *)lh_insert(ctx->sessions,c);
 	
 	/* s != NULL iff we already had a session with the given PID.
 	 * In this case, s == c should hold (then we did not really modify
 	 * ctx->sessions), or we're in trouble. */
 	if (s != NULL && s != c)
 		{
 		/* We *are* in trouble ... */
 		SSL_SESSION_list_remove(ctx,s);
 		SSL_SESSION_free(s);
 		/* ... so pretend the other session did not exist in cache
 		 * (we cannot handle two SSL_SESSION structures with identical
 		 * session ID in the same cache, which could happen e.g. when
 		 * two threads concurrently obtain the same session from an external
 		 * cache) */
 		s = NULL;
 		}
 
  	/* Put at the head of the queue unless it is already in the cache */
 	if (s == NULL)
 		SSL_SESSION_list_add(ctx,c);
 
 	if (s != NULL)
 		{
 		/* existing cache entry -- decrement previously incremented reference
 		 * count because it already takes into account the cache */
 
 		SSL_SESSION_free(s); /* s == c */
 		ret=0;
 		}
 	else
 		{
 		/* new cache entry -- remove old ones if cache has become too large */
 		
 		ret=1;
 
 		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
 			{
 			while (SSL_CTX_sess_number(ctx) >
 				SSL_CTX_sess_get_cache_size(ctx))
 				{
 				if (!remove_session_lock(ctx,
 					ctx->session_cache_tail, 0))
 					break;
 				else
 					ctx->stats.sess_cache_full++;
 				}
 			}
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	return(ret);
 	}
 
 int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
 {
 	return remove_session_lock(ctx, c, 1);
 }
 
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
 	{
 	SSL_SESSION *r;
 	int ret=0;
 
 	if ((c != NULL) && (c->session_id_length != 0))
 		{
 		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 		if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c)
 			{
 			ret=1;
 			r=(SSL_SESSION *)lh_delete(ctx->sessions,c);
 			SSL_SESSION_list_remove(ctx,c);
 			}
 
 		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 
 		if (ret)
 			{
 			r->not_resumable=1;
 			if (ctx->remove_session_cb != NULL)
 				ctx->remove_session_cb(ctx,r);
 			SSL_SESSION_free(r);
 			}
 		}
 	else
 		ret=0;
 	return(ret);
 	}
 
 void SSL_SESSION_free(SSL_SESSION *ss)
 	{
 	int i;
 
 	if(ss == NULL)
 	    return;
 
 	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
 #ifdef REF_PRINT
 	REF_PRINT("SSL_SESSION",ss);
 #endif
 	if (i > 0) return;
 #ifdef REF_CHECK
 	if (i < 0)
 		{
 		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
 		abort(); /* ok */
 		}
 #endif
 
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
 	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
 	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key);
 	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id);
 	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
 	if (ss->peer != NULL) X509_free(ss->peer);
 	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
 #ifndef OPENSSL_NO_TLSEXT
 	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
 	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
 #endif
 	OPENSSL_cleanse(ss,sizeof(*ss));
 	OPENSSL_free(ss);
 	}
 
 int SSL_set_session(SSL *s, SSL_SESSION *session)
 	{
 	int ret=0;
 	SSL_METHOD *meth;
 
 	if (session != NULL)
 		{
 		meth=s->ctx->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			meth=s->method->get_ssl_method(session->ssl_version);
 		if (meth == NULL)
 			{
 			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
 			return(0);
 			}
 
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			if (s->ctx->session_timeout == 0)
 				session->timeout=SSL_get_default_timeout(s);
 			else
 				session->timeout=s->ctx->session_timeout;
 			}
 
 #ifndef OPENSSL_NO_KRB5
                 if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
                     session->krb5_client_princ_len > 0)
                 {
                     s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
                     memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
                             session->krb5_client_princ_len);
                     s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
                 }
 #endif /* OPENSSL_NO_KRB5 */
 
 		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
 		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
 		if (s->session != NULL)
 			SSL_SESSION_free(s->session);
 		s->session=session;
 		s->verify_result = s->session->verify_result;
 		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
 		ret=1;
 		}
 	else
 		{
 		if (s->session != NULL)
 			{
 			SSL_SESSION_free(s->session);
 			s->session=NULL;
 			}
 
 		meth=s->ctx->method;
 		if (meth != s->method)
 			{
 			if (!SSL_set_ssl_method(s,meth))
 				return(0);
 			}
 		ret=1;
 		}
 	return(ret);
 	}
 
 long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->timeout=t;
 	return(1);
 	}
 
 long SSL_SESSION_get_timeout(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->timeout);
 	}
 
 long SSL_SESSION_get_time(const SSL_SESSION *s)
 	{
 	if (s == NULL) return(0);
 	return(s->time);
 	}
 
 long SSL_SESSION_set_time(SSL_SESSION *s, long t)
 	{
 	if (s == NULL) return(0);
 	s->time=t;
 	return(t);
 	}
 
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
 	{
 	long l;
 	if (s == NULL) return(0);
 	l=s->session_timeout;
 	s->session_timeout=t;
 	return(l);
 	}
 
 long SSL_CTX_get_timeout(const SSL_CTX *s)
 	{
 	if (s == NULL) return(0);
 	return(s->session_timeout);
 	}
 
 typedef struct timeout_param_st
 	{
 	SSL_CTX *ctx;
 	long time;
 	LHASH *cache;
 	} TIMEOUT_PARAM;
 
 static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p)
 	{
 	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
 		{
 		/* The reason we don't call SSL_CTX_remove_session() is to
 		 * save on locking overhead */
 		lh_delete(p->cache,s);
 		SSL_SESSION_list_remove(p->ctx,s);
 		s->not_resumable=1;
 		if (p->ctx->remove_session_cb != NULL)
 			p->ctx->remove_session_cb(p->ctx,s);
 		SSL_SESSION_free(s);
 		}
 	}
 
 static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *)
 
 void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
 	{
 	unsigned long i;
 	TIMEOUT_PARAM tp;
 
 	tp.ctx=s;
 	tp.cache=s->sessions;
 	if (tp.cache == NULL) return;
 	tp.time=t;
 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
 	i=tp.cache->down_load;
 	tp.cache->down_load=0;
 	lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp);
 	tp.cache->down_load=i;
 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 	}
 
 int ssl_clear_bad_session(SSL *s)
 	{
 	if (	(s->session != NULL) &&
 		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
 		!(SSL_in_init(s) || SSL_in_before(s)))
 		{
 		SSL_CTX_remove_session(s->ctx,s->session);
 		return(1);
 		}
 	else
 		return(0);
 	}
 
 /* locked by SSL_CTX in the calling function */
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next == NULL) || (s->prev == NULL)) return;
 
 	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
 		{ /* last element in list */
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* only one element in list */
 			ctx->session_cache_head=NULL;
 			ctx->session_cache_tail=NULL;
 			}
 		else
 			{
 			ctx->session_cache_tail=s->prev;
 			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 			}
 		}
 	else
 		{
 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
 			{ /* first element in list */
 			ctx->session_cache_head=s->next;
 			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 			}
 		else
 			{ /* middle of list */
 			s->next->prev=s->prev;
 			s->prev->next=s->next;
 			}
 		}
 	s->prev=s->next=NULL;
 	}
 
 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
 	{
 	if ((s->next != NULL) && (s->prev != NULL))
 		SSL_SESSION_list_remove(ctx,s);
 
 	if (ctx->session_cache_head == NULL)
 		{
 		ctx->session_cache_head=s;
 		ctx->session_cache_tail=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
 		}
 	else
 		{
 		s->next=ctx->session_cache_head;
 		s->next->prev=s;
 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
 		ctx->session_cache_head=s;
 		}
 	}
 
 void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
 	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
 	{
 	ctx->new_session_cb=cb;
 	}
 
 int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
 	{
 	return ctx->new_session_cb;
 	}
 
 void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
 	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
 	{
 	ctx->remove_session_cb=cb;
 	}
 
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
 	{
 	return ctx->remove_session_cb;
 	}
 
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
 	SSL_SESSION *(*cb)(struct ssl_st *ssl,
 	         unsigned char *data,int len,int *copy))
 	{
 	ctx->get_session_cb=cb;
 	}
 
 SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
 	         unsigned char *data,int len,int *copy)
 	{
 	return ctx->get_session_cb;
 	}
 
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, 
 	void (*cb)(const SSL *ssl,int type,int val))
 	{
 	ctx->info_callback=cb;
 	}
 
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
 	{
 	return ctx->info_callback;
 	}
 
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
 	{
 	ctx->client_cert_cb=cb;
 	}
 
 int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
 	{
 	return ctx->client_cert_cb;
 	}
 
 #ifndef OPENSSL_NO_ENGINE
 int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
 	{
 	if (!ENGINE_init(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
 		return 0;
 		}
 	if(!ENGINE_get_ssl_client_cert_function(e))
 		{
 		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
 		ENGINE_finish(e);
 		return 0;
 		}
 	ctx->client_cert_engine = e;
 	return 1;
 	}
 #endif
 
 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
 	{
 	ctx->app_gen_cookie_cb=cb;
 	}
 
 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
 	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
 	{
 	ctx->app_verify_cookie_cb=cb;
 	}
 
Index: releng/9.3/sys/conf/newvers.sh
===================================================================
--- releng/9.3/sys/conf/newvers.sh	(revision 284294)
+++ releng/9.3/sys/conf/newvers.sh	(revision 284295)
@@ -1,160 +1,160 @@
 #!/bin/sh -
 #
 # Copyright (c) 1984, 1986, 1990, 1993
 #	The Regents of the University of California.  All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
 # 1. Redistributions of source code must retain the above copyright
 #    notice, this list of conditions and the following disclaimer.
 # 2. Redistributions in binary form must reproduce the above copyright
 #    notice, this list of conditions and the following disclaimer in the
 #    documentation and/or other materials provided with the distribution.
 # 4. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
 #
 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
 #	@(#)newvers.sh	8.1 (Berkeley) 4/20/94
 # $FreeBSD$
 
 TYPE="FreeBSD"
 REVISION="9.3"
-BRANCH="RELEASE-p15"
+BRANCH="RELEASE-p16"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi
 RELEASE="${REVISION}-${BRANCH}"
 VERSION="${TYPE} ${RELEASE}"
 
 if [ "X${SYSDIR}" = "X" ]; then
     SYSDIR=$(dirname $0)/..
 fi
 
 if [ "X${PARAMFILE}" != "X" ]; then
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${PARAMFILE})
 else
 	RELDATE=$(awk '/__FreeBSD_version.*propagated to newvers/ {print $3}' \
 		${SYSDIR}/sys/param.h)
 fi
 
 b=share/examples/etc/bsd-style-copyright
 year=`date '+%Y'`
 # look for copyright template
 for bsd_copyright in ../$b ../../$b ../../../$b /usr/src/$b /usr/$b
 do
 	if [ -r "$bsd_copyright" ]; then
 		COPYRIGHT=`sed \
 		    -e "s/\[year\]/1992-$year/" \
 		    -e 's/\[your name here\]\.* /The FreeBSD Project./' \
 		    -e 's/\[your name\]\.*/The FreeBSD Project./' \
 		    -e '/\[id for your version control system, if any\]/d' \
 		    $bsd_copyright` 
 		break
 	fi
 done
 
 # no copyright found, use a dummy
 if [ X"$COPYRIGHT" = X ]; then
 	COPYRIGHT="/*-
  * Copyright (c) 1992-$year The FreeBSD Project.
  * All rights reserved.
  *
  */"
 fi
 
 # add newline
 COPYRIGHT="$COPYRIGHT
 "
 
 LC_ALL=C; export LC_ALL
 if [ ! -r version ]
 then
 	echo 0 > version
 fi
 
 touch version
 v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
 i=`${MAKE:-make} -V KERN_IDENT`
 compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
 
 for dir in /bin /usr/bin /usr/local/bin; do
 	if [ -x "${dir}/svnversion" ] ; then
 		svnversion=${dir}/svnversion
 		break
 	fi
 done
 if [ -d "${SYSDIR}/../.git" ] ; then
 	for dir in /bin /usr/bin /usr/local/bin; do
 		if [ -x "${dir}/git" ] ; then
 			git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git"
 			break
 		fi
 	done
 fi
 
 if [ -n "$svnversion" ] ; then
 	echo "$svnversion"
 	svn=`cd ${SYSDIR} && $svnversion`
 	case "$svn" in
 	[0-9]*)	svn=" r${svn}" ;;
 	*)	unset svn ;;
 	esac
 fi
 
 if [ -n "$git_cmd" ] ; then
 	git=`$git_cmd rev-parse --verify --short HEAD 2>/dev/null`
 	svn=`$git_cmd svn find-rev $git 2>/dev/null`
 	if [ -n "$svn" ] ; then
 		svn=" r${svn}"
 		git="=${git}"
 	else
 		svn=`$git_cmd log | fgrep 'git-svn-id:' | head -1 | \
 		     sed -n 's/^.*@\([0-9][0-9]*\).*$/\1/p'`
 		if [ -z "$svn" ] ; then
 			svn=`$git_cmd log --format='format:%N' | \
 			     grep '^svn ' | head -1 | \
 			     sed -n 's/^.*revision=\([0-9][0-9]*\).*$/\1/p'`
 		fi
 		if [ -n "$svn" ] ; then
 			svn=" r${svn}"
 			git="+${git}"
 		else
 			git=" ${git}"
 		fi
 	fi
 	if $git_cmd --work-tree=${SYSDIR}/.. diff-index \
 	    --name-only HEAD | read dummy; then
 		git="${git}-dirty"
 	fi
 fi
 
 cat << EOF > vers.c
 $COPYRIGHT
 #define SCCSSTR "@(#)${VERSION} #${v}${svn}${git}: ${t}"
 #define VERSTR "${VERSION} #${v}${svn}${git}: ${t}\\n    ${u}@${h}:${d}\\n"
 #define RELSTR "${RELEASE}"
 
 char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR;
 char version[sizeof(VERSTR) > 256 ? sizeof(VERSTR) : 256] = VERSTR;
 char compiler_version[] = "${compiler_v}";
 char ostype[] = "${TYPE}";
 char osrelease[sizeof(RELSTR) > 32 ? sizeof(RELSTR) : 32] = RELSTR;
 int osreldate = ${RELDATE};
 char kern_ident[] = "${i}";
 EOF
 
 echo $((v + 1)) > version