diff --git a/README.md b/README.md index fb9b08a8..35d1bb35 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Currently there are no releases of the server. You will need to have a developme ## Build Requirements * SBT 0.13.x -* Scala 2.11.7 +* Scala 2.11.8 * https://github.com/psforever/PSCrypto - binary DLL (Windows) or Shared Library (Linux) placed in the root directory of the project. -* PSCrypto v1.0 +* PSCrypto v1.1 ## Setting up a Build Environment PSF-LoginServer is built using Simple Build Tool (SBT), which allows it to be built on any platform. SBT is the Scala version of Make, but is more powerful as build definitions are written in Scala. SBT is distributed as a Java JAR and the only dependency it has is a JDK. @@ -19,11 +19,11 @@ PSF-LoginServer is built using Simple Build Tool (SBT), which allows it to be bu This project is tested with the official [JDK 8 from Oracle](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html). Download and install it for your system in order to start compiling Scala. If you are new to Scala, this may seem strange to be installing Java for Scala. Scala runs on top of the Java Virtual Machine, meaning it generates `.class` and `.jar` files and uses the `java` executable. Essentially, Scala is just a compiler that targets the JVM, which is its runtime. ### Downloading the Scala Development Kit -In order to use scala, you need the compiler `scalac`. This is equivalent to Java's `javac`, but for the Scala language. [Grab the 2.11.7 version from Scala-Lang.org](http://www.scala-lang.org/download/2.11.7.html). +In order to use scala, you need the compiler `scalac`. This is equivalent to Java's `javac`, but for the Scala language. [Grab the 2.11.8 version from Scala-Lang.org](http://www.scala-lang.org/download/2.11.8.html). Install this on to your system and the compiler and Scala REPL will be added to your PATH. ### Downloading PSCrypto -The server requires PSCrypto in order to run. [Download the latest release](https://github.com/psforever/PSCrypto/releases/download/v1.0/pscrypto-lib-1.0.zip) and extract the ZIP in to the top level of your source directory. +The server requires PSCrypto in order to run. [Download the latest release](https://github.com/psforever/PSCrypto/releases/download/v1.1/pscrypto-lib-1.1.zip) and extract the ZIP in to the top level of your source directory. SBT and IDEA will automatically find the required libraries when running. diff --git a/common/src/main/scala/net/psforever/crypto/CryptoInterface.scala b/common/src/main/scala/net/psforever/crypto/CryptoInterface.scala index f1423880..c6e7e300 100644 --- a/common/src/main/scala/net/psforever/crypto/CryptoInterface.scala +++ b/common/src/main/scala/net/psforever/crypto/CryptoInterface.scala @@ -1,20 +1,27 @@ // Copyright (c) 2016 PSForever.net to present package net.psforever.crypto +import com.sun.jna.ptr.IntByReference import net.psforever.IFinalizable import sna.Library -import com.sun.jna.Pointer +import com.sun.jna.{NativeLibrary, Pointer} import scodec.bits.ByteVector object CryptoInterface { final val libName = "pscrypto" final val fullLibName = libName + final val PSCRYPTO_VERSION_MAJOR = 1 + final val PSCRYPTO_VERSION_MINOR = 1 + final val psLib = new Library(libName) final val RC5_BLOCK_SIZE = 8 final val MD5_MAC_SIZE = 16 val functionsList = List( + "PSCrypto_Init", + "PSCrypto_Get_Version", + "PSCrypto_Version_String", "RC5_Init", "RC5_Encrypt", "RC5_Decrypt", @@ -27,10 +34,22 @@ object CryptoInterface { ) /** - * Used to initialize the crypto library at runtime. This allows + * Used to initialize the crypto library at runtime. The version is checked and + * all functions are mapped. */ def initialize() : Unit = { + // preload all library functions for speed functionsList foreach psLib.prefetch + + val libraryMajor = new IntByReference + val libraryMinor = new IntByReference + + psLib.PSCrypto_Get_Version(libraryMajor, libraryMinor)[Unit] + + if(!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) { + throw new IllegalArgumentException(s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " + + s"${PSCRYPTO_VERSION_MAJOR}.${PSCRYPTO_VERSION_MINOR}") + } } /** @@ -67,14 +86,16 @@ object CryptoInterface { } /** - * Checks if two MAC values are the same in constant time, preventing a timing attack for MAC forgery - * - * @param mac1 - * @param mac2 + * Checks if two Message Authentication Codes are the same in constant time, + * preventing a timing attack for MAC forgery + * + * @param mac1 A MAC value + * @param mac2 Another MAC value */ def verifyMAC(mac1 : ByteVector, mac2 : ByteVector) : Boolean = { var okay = true + // prevent byte by byte guessing if(mac1.length != mac2.length) return false @@ -163,6 +184,7 @@ object CryptoInterface { override def close = { if(started) { + // TODO: zero private key material psLib.Free_DH(dhHandle)[Unit] started = false } diff --git a/pslogin/src/main/scala/PsLogin.scala b/pslogin/src/main/scala/PsLogin.scala index 04a04ef2..2614b10b 100644 --- a/pslogin/src/main/scala/PsLogin.scala +++ b/pslogin/src/main/scala/PsLogin.scala @@ -123,8 +123,14 @@ object PsLogin { } catch { case e : UnsatisfiedLinkError => - logger.error(e)("Unable to initialize " + CryptoInterface.libName) - CryptoInterface.printEnvironment() + logger.error("Unable to initialize " + CryptoInterface.libName) + logger.error(e)("This means that your PSCrypto version is out of date. Get the latest version from the README" + + " https://github.com/psforever/PSF-LoginServer#downloading-pscrypto") + sys.exit(1) + case e : IllegalArgumentException => + logger.error("Unable to initialize " + CryptoInterface.libName) + logger.error(e)("This means that your PSCrypto version is out of date. Get the latest version from the README" + + " https://github.com/psforever/PSF-LoginServer#downloading-pscrypto") sys.exit(1) }