cryptonite 0.15.1 → 0.16
raw patch · 9 files changed
+502/−82 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +3/−4
- Crypto/Cipher/Blowfish/Primitive.hs +1/−3
- Crypto/KDF/Scrypt.hs +1/−1
- Crypto/Random/EntropyPool.hs +6/−4
- README.md +15/−16
- cbits/cryptonite_rdrand.c +21/−47
- cbits/curve25519/curve25519-donna-c64.c +447/−0
- cryptonite.cabal +8/−6
- tests/BCrypt.hs +0/−1
CHANGELOG.md view
@@ -1,9 +1,8 @@-## 0.15.1+## 0.16 -* Add error check on salt length in bcrypt-* Fix buffer length in scrypt (Luke Taylor)-* build fixes for i686 and arm related to rdrand * Fix basepoint for Ed448++* Enable 64-bit Curve25519 implementation ## 0.15
Crypto/Cipher/Blowfish/Primitive.hs view
@@ -79,9 +79,7 @@ -- Cost must be between 4 and 31 inclusive -- See <https://www.usenix.org/conference/1999-usenix-annual-technical-conference/future-adaptable-password-scheme> eksBlowfish :: (ByteArrayAccess salt, ByteArrayAccess password) => Int -> salt -> password -> Context-eksBlowfish cost salt key- | B.length salt /= 16 = error "bcrypt salt must be 16 bytes"- | otherwise = makeKeySchedule key (Just (salt, cost))+eksBlowfish cost salt key = makeKeySchedule key (Just (salt, cost)) coreCrypto :: Context -> Word64 -> Word64 coreCrypto (BF p s0 s1 s2 s3) input = doRound input 0
Crypto/KDF/Scrypt.hs view
@@ -53,7 +53,7 @@ let b = PBKDF2.generate prf (PBKDF2.Parameters 1 intLen) password salt :: B.Bytes newSalt <- B.copy b $ \bPtr -> allocaBytesAligned (128*(fromIntegral $ n params)*(r params)) 8 $ \v ->- allocaBytesAligned (256*r params + 64) 8 $ \xy -> do+ allocaBytesAligned (256*r params) 8 $ \xy -> do forM_ [0..(p params-1)] $ \i -> ccryptonite_scrypt_smix (bPtr `plusPtr` (i * 128 * (r params))) (fromIntegral $ r params) (n params) v xy
Crypto/Random/EntropyPool.hs view
@@ -21,8 +21,8 @@ import Foreign.Marshal.Utils (copyBytes) import Foreign.Ptr (plusPtr, Ptr) --- | Pool of Entropy. contains a self mutating pool of entropy,--- that is always guarantee to contains data.+-- | Pool of Entropy. Contains a self-mutating pool of entropy,+-- that is always guaranteed to contain data. data EntropyPool = EntropyPool [EntropyBackend] (MVar Int) ScrubbedBytes -- size of entropy pool by default@@ -31,7 +31,8 @@ -- | Create a new entropy pool of a specific size ----- While you can create as many entropy pool as you want, the pool can be shared between multiples RNGs.+-- While you can create as many entropy pools as you want,+-- the pool can be shared between multiples RNGs. createEntropyPoolWith :: Int -> [EntropyBackend] -> IO EntropyPool createEntropyPoolWith poolSize backends = do m <- newMVar 0@@ -40,7 +41,8 @@ -- | Create a new entropy pool with a default size. ----- While you can create as many entropy pool as you want, the pool can be shared between multiples RNGs.+-- While you can create as many entropy pools as you want,+-- the pool can be shared between multiples RNGs. createEntropyPool :: IO EntropyPool createEntropyPool = do backends <- catMaybes `fmap` sequence supportedBackends
README.md view
@@ -2,27 +2,25 @@ ========== [](https://gitter.im/vincenthz/cryptonite?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)-[](https://travis-ci.org/vincenthz/cryptonite)+[](https://travis-ci.org/haskell-crypto/cryptonite) [](http://en.wikipedia.org/wiki/BSD_licenses) [](http://haskell.org) Cryptonite is a haskell repository of cryptographic primitives. Each crypto-algorithm have specificities, that are hard to wrap in common APIs and types,-so instead of trying to provide a common ground for algorithms that wouldn't-allow to provide all different usage or a really complicated system, this just-provide a non-consistant low-level API.+algorithm has specificities that are hard to wrap in common APIs and types,+so instead of trying to provide a common ground for algorithms, this package+provides a non-consistent low-level API. -If you have no idea what're you doing, please do not use this directly, rely on-higher level protocols or higher level implementation.+If you have no idea what you're doing, please do not use this directly.+Instead, rely on higher level protocols or implementations. Documentation: [cryptonite on hackage](http://hackage.haskell.org/package/cryptonite) Versioning ---------- -Development versions are an incremental number prefixed by 0.-No specific meaning is associated with the versions, specially-no API stability.+Development versions are an incremental number prefixed by 0. There is no+API stability between development versions. Production versions : TBD @@ -35,7 +33,7 @@ Support ------- -cryptonite supports the following platform:+cryptonite supports the following platforms: * Windows >= 8 * OSX >= 10.8@@ -55,21 +53,22 @@ * GHC 7.8.x * GHC 7.10.x -Further platforms and architectures probably works too, but until maintainer(s) don't have regular-access to them, we can't commit for further support+Further platforms and architectures probably work too, but since the+maintainer(s) don't have regular access to them, we can't commit to+further support. Known Building Issues --------------------- -on OSX <= 10.7, the system compiler doesn't understand the '-maes' option, and+On OSX <= 10.7, the system compiler doesn't understand the '-maes' option, and with the lack of autodetection feature builtin in .cabal file, it is left on the user to disable the aesni. See the [Disabling AESNI] section Disabling AESNI --------------- -It may be useful to disable AESNI (for building, testing or runtime purpose), and one can do that with the-*support_aesni* flag.+It may be useful to disable AESNI for building, testing or runtime purposes.+This is achieved with the *support_aesni* flag. As part of configure of cryptonite:
cbits/cryptonite_rdrand.c view
@@ -37,53 +37,16 @@ int cryptonite_cpu_has_rdrand() { uint32_t ax,bx,cx,dx,func=1;-#if defined(__PIC__) && defined(__i386__)- __asm__ volatile ("mov %%ebx, %%edi;" "cpuid;" "xchgl %%ebx, %%edi;"- : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) : "a" (func));-#else __asm__ volatile ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));-#endif return (cx & 0x40000000); } -/* inline encoding of 'rdrand %rax' to cover old binutils- * - no inputs- * - 'cc' to the clobber list as we modify condition code.- * - output of rdrand in rax and have a 8 bit error condition- */-#define inline_rdrand_rax(val, err) \- asm(".byte 0x48,0x0f,0xc7,0xf0; setc %1" \- : "=a" (val), "=q" (err) \- : \- : "cc")--/* inline encoding of 'rdrand %eax' to cover old binutils- * - no inputs- * - 'cc' to the clobber list as we modify condition code.- * - output of rdrand in eax and have a 8 bit error condition- */-#define inline_rdrand_eax(val, err) \- asm(".byte 0x0f,0xc7,0xf0; setc %1" \- : "=a" (val), "=q" (err) \- : \- : "cc")--#ifdef __x86_64__-# define RDRAND_SZ 8-# define RDRAND_T uint64_t-#define inline_rdrand(val, err) err = cryptonite_rdrand_step(&val)-#else-# define RDRAND_SZ 4-# define RDRAND_T uint32_t-#define inline_rdrand(val, err) err = cryptonite_rdrand_step(&val)-#endif- /* sadly many people are still using an old binutils, * leading to report that instruction is not recognized. */-#if 1+#if 0 /* Returns 1 on success */-static inline int cryptonite_rdrand_step(RDRAND_T *buffer)+static inline int crypto_random_rdrand64_step(uint64_t *buffer) { unsigned char err; asm volatile ("rdrand %0; setc %1" : "=r" (*buffer), "=qm" (err));@@ -91,17 +54,28 @@ } #endif +/* inline encoding of 'rdrand %rax' to cover old binutils+ * - no inputs+ * - 'cc' to the clobber list as we modify condition code.+ * - output of rdrand in rax and have a 8 bit error condition+ */+#define inline_rdrand_rax(val, err) \+ asm(".byte 0x48,0x0f,0xc7,0xf0; setc %1" \+ : "=a" (val), "=q" (err) \+ : \+ : "cc")+ /* Returns the number of bytes succesfully generated */ int cryptonite_get_rand_bytes(uint8_t *buffer, size_t len) {- RDRAND_T tmp;- int aligned = (intptr_t) buffer % RDRAND_SZ;+ uint64_t tmp;+ int aligned = (intptr_t) buffer % 8; int orig_len = len;- int to_alignment = RDRAND_SZ - aligned;+ int to_alignment = 8 - aligned; uint8_t ok; if (aligned != 0) {- inline_rdrand(tmp, ok);+ inline_rdrand_rax(tmp, ok); if (!ok) return 0; memcpy(buffer, (uint8_t *) &tmp, to_alignment);@@ -109,15 +83,15 @@ len -= to_alignment; } - for (; len >= RDRAND_SZ; buffer += RDRAND_SZ, len -= RDRAND_SZ) {- inline_rdrand(tmp, ok);+ for (; len >= 8; buffer += 8, len -= 8) {+ inline_rdrand_rax(tmp, ok); if (!ok) return (orig_len - len);- *((RDRAND_T *) buffer) = tmp;+ *((uint64_t *) buffer) = tmp; } if (len > 0) {- inline_rdrand(tmp, ok);+ inline_rdrand_rax(tmp, ok); if (!ok) return (orig_len - len); memcpy(buffer, (uint8_t *) &tmp, len);
+ cbits/curve25519/curve25519-donna-c64.c view
@@ -0,0 +1,447 @@+/* Copyright 2008, Google Inc.+ * All rights reserved.+ *+ * Code released into the public domain.+ *+ * curve25519-donna: Curve25519 elliptic curve, public key function+ *+ * http://code.google.com/p/curve25519-donna/+ *+ * Adam Langley <agl@imperialviolet.org>+ *+ * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>+ *+ * More information about curve25519 can be found here+ * http://cr.yp.to/ecdh.html+ *+ * djb's sample implementation of curve25519 is written in a special assembly+ * language called qhasm and uses the floating point registers.+ *+ * This is, almost, a clean room reimplementation from the curve25519 paper. It+ * uses many of the tricks described therein. Only the crecip function is taken+ * from the sample implementation.+ */++#include <string.h>+#include <stdint.h>++typedef uint8_t u8;+typedef uint64_t limb;+typedef limb felem[5];+// This is a special gcc mode for 128-bit integers. It's implemented on 64-bit+// platforms only as far as I know.+typedef unsigned uint128_t __attribute__((mode(TI)));++#undef force_inline+#define force_inline __attribute__((always_inline))++/* Sum two numbers: output += in */+static inline void force_inline+fsum(limb *output, const limb *in) {+ output[0] += in[0];+ output[1] += in[1];+ output[2] += in[2];+ output[3] += in[3];+ output[4] += in[4];+}++/* Find the difference of two numbers: output = in - output+ * (note the order of the arguments!)+ *+ * Assumes that out[i] < 2**52+ * On return, out[i] < 2**55+ */+static inline void force_inline+fdifference_backwards(felem out, const felem in) {+ /* 152 is 19 << 3 */+ static const limb two54m152 = (((limb)1) << 54) - 152;+ static const limb two54m8 = (((limb)1) << 54) - 8;++ out[0] = in[0] + two54m152 - out[0];+ out[1] = in[1] + two54m8 - out[1];+ out[2] = in[2] + two54m8 - out[2];+ out[3] = in[3] + two54m8 - out[3];+ out[4] = in[4] + two54m8 - out[4];+}++/* Multiply a number by a scalar: output = in * scalar */+static inline void force_inline+fscalar_product(felem output, const felem in, const limb scalar) {+ uint128_t a;++ a = ((uint128_t) in[0]) * scalar;+ output[0] = ((limb)a) & 0x7ffffffffffff;++ a = ((uint128_t) in[1]) * scalar + ((limb) (a >> 51));+ output[1] = ((limb)a) & 0x7ffffffffffff;++ a = ((uint128_t) in[2]) * scalar + ((limb) (a >> 51));+ output[2] = ((limb)a) & 0x7ffffffffffff;++ a = ((uint128_t) in[3]) * scalar + ((limb) (a >> 51));+ output[3] = ((limb)a) & 0x7ffffffffffff;++ a = ((uint128_t) in[4]) * scalar + ((limb) (a >> 51));+ output[4] = ((limb)a) & 0x7ffffffffffff;++ output[0] += (a >> 51) * 19;+}++/* Multiply two numbers: output = in2 * in+ *+ * output must be distinct to both inputs. The inputs are reduced coefficient+ * form, the output is not.+ *+ * Assumes that in[i] < 2**55 and likewise for in2.+ * On return, output[i] < 2**52+ */+static inline void force_inline+fmul(felem output, const felem in2, const felem in) {+ uint128_t t[5];+ limb r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c;++ r0 = in[0];+ r1 = in[1];+ r2 = in[2];+ r3 = in[3];+ r4 = in[4];++ s0 = in2[0];+ s1 = in2[1];+ s2 = in2[2];+ s3 = in2[3];+ s4 = in2[4];++ t[0] = ((uint128_t) r0) * s0;+ t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0;+ t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1;+ t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1;+ t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2;++ r4 *= 19;+ r1 *= 19;+ r2 *= 19;+ r3 *= 19;++ t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2;+ t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3;+ t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4;+ t[3] += ((uint128_t) r4) * s4;++ r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51);+ t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51);+ t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51);+ t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51);+ t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51);+ r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff;+ r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff;+ r2 += c;++ output[0] = r0;+ output[1] = r1;+ output[2] = r2;+ output[3] = r3;+ output[4] = r4;+}++static inline void force_inline+fsquare_times(felem output, const felem in, limb count) {+ uint128_t t[5];+ limb r0,r1,r2,r3,r4,c;+ limb d0,d1,d2,d4,d419;++ r0 = in[0];+ r1 = in[1];+ r2 = in[2];+ r3 = in[3];+ r4 = in[4];++ do {+ d0 = r0 * 2;+ d1 = r1 * 2;+ d2 = r2 * 2 * 19;+ d419 = r4 * 19;+ d4 = d419 * 2;++ t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 ));+ t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19));+ t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 ));+ t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 ));+ t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 ));++ r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51);+ t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51);+ t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51);+ t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51);+ t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51);+ r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff;+ r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff;+ r2 += c;+ } while(--count);++ output[0] = r0;+ output[1] = r1;+ output[2] = r2;+ output[3] = r3;+ output[4] = r4;+}++/* Load a little-endian 64-bit number */+static limb+load_limb(const u8 *in) {+ return+ ((limb)in[0]) |+ (((limb)in[1]) << 8) |+ (((limb)in[2]) << 16) |+ (((limb)in[3]) << 24) |+ (((limb)in[4]) << 32) |+ (((limb)in[5]) << 40) |+ (((limb)in[6]) << 48) |+ (((limb)in[7]) << 56);+}++static void+store_limb(u8 *out, limb in) {+ out[0] = in & 0xff;+ out[1] = (in >> 8) & 0xff;+ out[2] = (in >> 16) & 0xff;+ out[3] = (in >> 24) & 0xff;+ out[4] = (in >> 32) & 0xff;+ out[5] = (in >> 40) & 0xff;+ out[6] = (in >> 48) & 0xff;+ out[7] = (in >> 56) & 0xff;+}++/* Take a little-endian, 32-byte number and expand it into polynomial form */+static void+fexpand(limb *output, const u8 *in) {+ output[0] = load_limb(in) & 0x7ffffffffffff;+ output[1] = (load_limb(in+6) >> 3) & 0x7ffffffffffff;+ output[2] = (load_limb(in+12) >> 6) & 0x7ffffffffffff;+ output[3] = (load_limb(in+19) >> 1) & 0x7ffffffffffff;+ output[4] = (load_limb(in+24) >> 12) & 0x7ffffffffffff;+}++/* Take a fully reduced polynomial form number and contract it into a+ * little-endian, 32-byte array+ */+static void+fcontract(u8 *output, const felem input) {+ uint128_t t[5];++ t[0] = input[0];+ t[1] = input[1];+ t[2] = input[2];+ t[3] = input[3];+ t[4] = input[4];++ t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;+ t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;+ t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;+ t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;+ t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;++ t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;+ t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;+ t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;+ t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;+ t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;++ /* now t is between 0 and 2^255-1, properly carried. */+ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */++ t[0] += 19;++ t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;+ t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;+ t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;+ t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;+ t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;++ /* now between 19 and 2^255-1 in both cases, and offset by 19. */++ t[0] += 0x8000000000000 - 19;+ t[1] += 0x8000000000000 - 1;+ t[2] += 0x8000000000000 - 1;+ t[3] += 0x8000000000000 - 1;+ t[4] += 0x8000000000000 - 1;++ /* now between 2^255 and 2^256-20, and offset by 2^255. */++ t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;+ t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;+ t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;+ t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;+ t[4] &= 0x7ffffffffffff;++ store_limb(output, t[0] | (t[1] << 51));+ store_limb(output+8, (t[1] >> 13) | (t[2] << 38));+ store_limb(output+16, (t[2] >> 26) | (t[3] << 25));+ store_limb(output+24, (t[3] >> 39) | (t[4] << 12));+}++/* Input: Q, Q', Q-Q'+ * Output: 2Q, Q+Q'+ *+ * x2 z3: long form+ * x3 z3: long form+ * x z: short form, destroyed+ * xprime zprime: short form, destroyed+ * qmqp: short form, preserved+ */+static void+fmonty(limb *x2, limb *z2, /* output 2Q */+ limb *x3, limb *z3, /* output Q + Q' */+ limb *x, limb *z, /* input Q */+ limb *xprime, limb *zprime, /* input Q' */+ const limb *qmqp /* input Q - Q' */) {+ limb origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5],+ zzprime[5], zzzprime[5];++ memcpy(origx, x, 5 * sizeof(limb));+ fsum(x, z);+ fdifference_backwards(z, origx); // does x - z++ memcpy(origxprime, xprime, sizeof(limb) * 5);+ fsum(xprime, zprime);+ fdifference_backwards(zprime, origxprime);+ fmul(xxprime, xprime, z);+ fmul(zzprime, x, zprime);+ memcpy(origxprime, xxprime, sizeof(limb) * 5);+ fsum(xxprime, zzprime);+ fdifference_backwards(zzprime, origxprime);+ fsquare_times(x3, xxprime, 1);+ fsquare_times(zzzprime, zzprime, 1);+ fmul(z3, zzzprime, qmqp);++ fsquare_times(xx, x, 1);+ fsquare_times(zz, z, 1);+ fmul(x2, xx, zz);+ fdifference_backwards(zz, xx); // does zz = xx - zz+ fscalar_product(zzz, zz, 121665);+ fsum(zzz, xx);+ fmul(z2, zz, zzz);+}++// -----------------------------------------------------------------------------+// Maybe swap the contents of two limb arrays (@a and @b), each @len elements+// long. Perform the swap iff @swap is non-zero.+//+// This function performs the swap without leaking any side-channel+// information.+// -----------------------------------------------------------------------------+static void+swap_conditional(limb a[5], limb b[5], limb iswap) {+ unsigned i;+ const limb swap = -iswap;++ for (i = 0; i < 5; ++i) {+ const limb x = swap & (a[i] ^ b[i]);+ a[i] ^= x;+ b[i] ^= x;+ }+}++/* Calculates nQ where Q is the x-coordinate of a point on the curve+ *+ * resultx/resultz: the x coordinate of the resulting curve point (short form)+ * n: a little endian, 32-byte number+ * q: a point of the curve (short form)+ */+static void+cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {+ limb a[5] = {0}, b[5] = {1}, c[5] = {1}, d[5] = {0};+ limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;+ limb e[5] = {0}, f[5] = {1}, g[5] = {0}, h[5] = {1};+ limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;++ unsigned i, j;++ memcpy(nqpqx, q, sizeof(limb) * 5);++ for (i = 0; i < 32; ++i) {+ u8 byte = n[31 - i];+ for (j = 0; j < 8; ++j) {+ const limb bit = byte >> 7;++ swap_conditional(nqx, nqpqx, bit);+ swap_conditional(nqz, nqpqz, bit);+ fmonty(nqx2, nqz2,+ nqpqx2, nqpqz2,+ nqx, nqz,+ nqpqx, nqpqz,+ q);+ swap_conditional(nqx2, nqpqx2, bit);+ swap_conditional(nqz2, nqpqz2, bit);++ t = nqx;+ nqx = nqx2;+ nqx2 = t;+ t = nqz;+ nqz = nqz2;+ nqz2 = t;+ t = nqpqx;+ nqpqx = nqpqx2;+ nqpqx2 = t;+ t = nqpqz;+ nqpqz = nqpqz2;+ nqpqz2 = t;++ byte <<= 1;+ }+ }++ memcpy(resultx, nqx, sizeof(limb) * 5);+ memcpy(resultz, nqz, sizeof(limb) * 5);+}+++// -----------------------------------------------------------------------------+// Shamelessly copied from djb's code, tightened a little+// -----------------------------------------------------------------------------+static void+crecip(felem out, const felem z) {+ felem a,t0,b,c;++ /* 2 */ fsquare_times(a, z, 1); // a = 2+ /* 8 */ fsquare_times(t0, a, 2);+ /* 9 */ fmul(b, t0, z); // b = 9+ /* 11 */ fmul(a, b, a); // a = 11+ /* 22 */ fsquare_times(t0, a, 1);+ /* 2^5 - 2^0 = 31 */ fmul(b, t0, b);+ /* 2^10 - 2^5 */ fsquare_times(t0, b, 5);+ /* 2^10 - 2^0 */ fmul(b, t0, b);+ /* 2^20 - 2^10 */ fsquare_times(t0, b, 10);+ /* 2^20 - 2^0 */ fmul(c, t0, b);+ /* 2^40 - 2^20 */ fsquare_times(t0, c, 20);+ /* 2^40 - 2^0 */ fmul(t0, t0, c);+ /* 2^50 - 2^10 */ fsquare_times(t0, t0, 10);+ /* 2^50 - 2^0 */ fmul(b, t0, b);+ /* 2^100 - 2^50 */ fsquare_times(t0, b, 50);+ /* 2^100 - 2^0 */ fmul(c, t0, b);+ /* 2^200 - 2^100 */ fsquare_times(t0, c, 100);+ /* 2^200 - 2^0 */ fmul(t0, t0, c);+ /* 2^250 - 2^50 */ fsquare_times(t0, t0, 50);+ /* 2^250 - 2^0 */ fmul(t0, t0, b);+ /* 2^255 - 2^5 */ fsquare_times(t0, t0, 5);+ /* 2^255 - 21 */ fmul(out, t0, a);+}++int+cryptonite_curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {+ limb bp[5], x[5], z[5], zmone[5];+ uint8_t e[32];+ int i;++ for (i = 0;i < 32;++i) e[i] = secret[i];+ e[0] &= 248;+ e[31] &= 127;+ e[31] |= 64;++ fexpand(bp, basepoint);+ cmult(x, z, e, bp);+ crecip(zmone, z);+ fmul(z, x, zmone);+ fcontract(mypublic, z);+ return 0;+}
cryptonite.cabal view
@@ -1,5 +1,5 @@ Name: cryptonite-Version: 0.15.1+Version: 0.16 Synopsis: Cryptography Primitives sink Description: A repository of cryptographic primitives.@@ -10,7 +10,7 @@ . * MAC: HMAC, Poly1305 .- * Assymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519+ * Asymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519, Ed448 . * Key Derivation Function: PBKDF2, Scrypt, HKDF .@@ -41,9 +41,7 @@ cbits/ed448/*.h cbits/p256/*.h cbits/blake2/ref/*.h- cbits/blake2/ref/*.c cbits/blake2/sse/*.h- cbits/blake2/sse/*.c cbits/aes/x86ni_impl.c tests/*.hs @@ -201,7 +199,6 @@ , cbits/cryptonite_salsa.c , cbits/cryptonite_rc4.c , cbits/cryptonite_cpu.c- , cbits/curve25519/curve25519-donna.c , cbits/ed25519/ed25519.c , cbits/ed448/x448.c , cbits/p256/p256.c@@ -227,6 +224,11 @@ , cbits/cryptonite_scrypt.c include-dirs: cbits cbits/ed25519 + if arch(x86_64)+ C-sources: cbits/curve25519/curve25519-donna-c64.c+ else+ C-sources: cbits/curve25519/curve25519-donna.c+ -- FIXME armel or mispel is also little endian. -- might be a good idea to also add a runtime autodetect mode. -- ARCH_ENDIAN_UNKNOWN@@ -239,7 +241,7 @@ if arch(x86_64) CPP-options: -DARCH_X86_64 - if flag(support_rdrand) && (arch(i386) || arch(x86_64))+ if flag(support_rdrand) CPP-options: -DSUPPORT_RDRAND Other-modules: Crypto.Random.Entropy.RDRand c-sources: cbits/cryptonite_rdrand.c
tests/BCrypt.hs view
@@ -74,5 +74,4 @@ tests = testGroup "bcrypt" [ testGroup "KATs" makeKATs- , testCase "Invalid hash length" (assertEqual "" (Left "Invalid hash format") (validatePasswordEither B.empty ("$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s" :: B.ByteString))) ]