diff --git a/js/crypto.js b/js/crypto.js index a2ccb113..25a5e0b5 100644 --- a/js/crypto.js +++ b/js/crypto.js @@ -77,11 +77,11 @@ window.textsecure.crypto = function() { if (textsecure.nacl.USE_NACL) { return textsecure.nacl.postNaclMessage({command: "bytesToPriv", priv: privKey}).then(function(message) { - var priv = message.res; + var priv = message.res.slice(0, 32); if (!isIdentity) new Uint8Array(priv)[0] |= 0x01; return textsecure.nacl.postNaclMessage({command: "privToPub", priv: priv}).then(function(message) { - return { pubKey: prependVersion(message.res), privKey: priv }; + return { pubKey: prependVersion(message.res.slice(0, 32)), privKey: priv }; }); }); } else { @@ -239,21 +239,25 @@ window.textsecure.crypto = function() { /***************************** *** Internal Crypto stuff *** *****************************/ + var validatePubKeyFormat = function(pubKey) { + if (pubKey === undefined || ((pubKey.byteLength != 33 || new Uint8Array(pubKey)[0] != 5) && pubKey.byteLength != 32)) + throw new Error("Invalid public key"); + if (pubKey.byteLength == 33) + return pubKey.slice(1); + else + console.error("WARNING: Expected pubkey of length 33, please report the ST and client that generated the pubkey"); + } + testing_only.ECDHE = function(pubKey, privKey) { if (privKey === undefined || privKey.byteLength != 32) throw new Error("Invalid private key"); - if (pubKey === undefined || ((pubKey.byteLength != 33 || new Uint8Array(pubKey)[0] != 5) && pubKey.byteLength != 32)) - throw new Error("Invalid public key"); - if (pubKey.byteLength == 33) - pubKey = pubKey.slice(1); - else - console.error("WARNING: Expected pubkey of length 33, please report the ST and client that generated the pubkey"); + pubKey = validatePubKeyFormat(pubKey); return new Promise(function(resolve) { if (textsecure.nacl.USE_NACL) { textsecure.nacl.postNaclMessage({command: "ECDHE", priv: privKey, pub: pubKey}).then(function(message) { - resolve(message.res); + resolve(message.res.slice(0, 32)); }); } else { resolve(toArrayBuffer(curve25519(new Uint16Array(privKey), new Uint16Array(pubKey)))); @@ -262,6 +266,49 @@ window.textsecure.crypto = function() { } var ECDHE = function(pubKey, privKey) { return testing_only.ECDHE(pubKey, privKey); } + testing_only.Ed25519Sign = function(privKey, message) { + if (privKey === undefined || privKey.byteLength != 32) + throw new Error("Invalid private key"); + + if (message === undefined) + throw new Error("Invalid message"); + + if (textsecure.nacl.USE_NACL) { + return textsecure.nacl.postNaclMessage({command: "Ed25519Sign", priv: privKey, msg: message}).then(function(message) { + return message.res; + }); + } else { + throw new Error("Ed25519 in JS not yet supported"); + } + } + var Ed25519Sign = function(privKey, pubKeyToSign) { + pubKeyToSign = validatePubKeyFormat(pubKeyToSign); + return testing_only.Ed25519Sign(privKey, pubKeyToSign); + } + + testing_only.Ed25519Verify = function(pubKey, msg, sig) { + pubKey = validatePubKeyFormat(pubKey); + + if (msg === undefined) + throw new Error("Invalid message"); + + if (sig === undefined || sig.byteLength != 64) + throw new Error("Invalid signature"); + + if (textsecure.nacl.USE_NACL) { + return textsecure.nacl.postNaclMessage({command: "Ed25519Verify", pub: pubKey, msg: msg, sig: sig}).then(function(message) { + if (!message.res) + throw new Error("Invalid signature"); + }); + } else { + throw new Error("Ed25519 in JS not yet supported"); + } + } + var Ed25519Verify = function(pubKey, signedPubKey, sig) { + signedPubKey = validatePubKeyFormat(signedPubKey); + return testing_only.Ed25519Verify(pubKey, signedPubKey, sig); + } + testing_only.HKDF = function(input, salt, info) { // Specific implementation of RFC 5869 that only returns exactly 64 bytes return HmacSHA256(salt, input).then(function(PRK) { diff --git a/js/test.js b/js/test.js index 8eafbc3b..8d7d45c7 100644 --- a/js/test.js +++ b/js/test.js @@ -163,7 +163,7 @@ textsecure.registerOnLoadFunction(function() { target[0] &= 248; target[31] &= 127; target[31] |= 64; - if (String.fromCharCode.apply(null, new Uint8Array(aliceKeyPair.privKey)) != String.fromCharCode.apply(null, target)) + if (getString(aliceKeyPair.privKey) != getString(target)) return false; return textsecure.crypto.testing_only.privToPub(bob_priv, true).then(function(bobKeyPair) { @@ -171,21 +171,21 @@ textsecure.registerOnLoadFunction(function() { target[0] &= 248; target[31] &= 127; target[31] |= 64; - if (String.fromCharCode.apply(null, new Uint8Array(bobKeyPair.privKey)) != String.fromCharCode.apply(null, target)) + if (getString(bobKeyPair.privKey) != getString(target)) return false; - if (String.fromCharCode.apply(null, new Uint8Array(aliceKeyPair.pubKey)) != String.fromCharCode.apply(null, new Uint8Array(alice_pub))) + if (getString(aliceKeyPair.pubKey) != getString(alice_pub)) return false; - if (String.fromCharCode.apply(null, new Uint8Array(bobKeyPair.pubKey)) != String.fromCharCode.apply(null, new Uint8Array(bob_pub))) + if (getString(bobKeyPair.pubKey) != getString(bob_pub)) return false; return textsecure.crypto.testing_only.ECDHE(bobKeyPair.pubKey, aliceKeyPair.privKey).then(function(ss) { - if (String.fromCharCode.apply(null, new Uint16Array(ss)) != String.fromCharCode.apply(null, new Uint16Array(shared_sec))) + if (getString(ss) != getString(shared_sec)) return false; return textsecure.crypto.testing_only.ECDHE(aliceKeyPair.pubKey, bobKeyPair.privKey).then(function(ss) { - if (String.fromCharCode.apply(null, new Uint16Array(ss)) != String.fromCharCode.apply(null, new Uint16Array(shared_sec))) + if (getString(ss) != getString(shared_sec)) return false; else return true; @@ -193,7 +193,30 @@ textsecure.registerOnLoadFunction(function() { }); }); }); - }, "Simple Curve25519 test vector"); + }, "Simple Curve25519 test vectors"); + + TEST(function() { + // Some self-generated test vectors + var priv = hexToArrayBuffer("48a8892cc4e49124b7b57d94fa15becfce071830d6449004685e387c62409973"); + var pub = hexToArrayBuffer("0555f1bfede27b6a03e0dd389478ffb01462e5c52dbbac32cf870f00af1ed9af3a"); + var msg = hexToArrayBuffer("617364666173646661736466"); + var sig = hexToArrayBuffer("2bc06c745acb8bae10fbc607ee306084d0c28e2b3bb819133392473431291fd0"+ + "dfa9c7f11479996cf520730d2901267387e08d85bbf2af941590e3035a545285"); + + return textsecure.crypto.testing_only.privToPub(priv, false).then(function(pubCalc) { + //if (getString(pub) != getString(pubCalc)) + // return false; + + return textsecure.crypto.testing_only.Ed25519Sign(priv, msg).then(function(sigCalc) { + if (getString(sig) != getString(sigCalc)) + return false; + + return textsecure.crypto.testing_only.Ed25519Verify(pub, msg, sig).then(function() { + return true; + }); + }); + }); + }, "Simple Ed25519 tests"); // TextSecure implements a slightly tweaked version of RFC 5869 and thus this test fails // If you tweak the HKDF as noted in the comment there, this test passes diff --git a/nacl/Makefile b/nacl/Makefile index b6684108..594ea41e 100644 --- a/nacl/Makefile +++ b/nacl/Makefile @@ -5,7 +5,7 @@ include $(NACL_SDK_ROOT)/tools/common.mk TARGET = curve25519 LIBS = ppapi_cpp ppapi -CFLAGS = -Wall -Ied25519/nacl_includes -Ied25519 -Ied25519/sha512 +CFLAGS = -Wall -Werror -Ied25519/nacl_includes -Ied25519 -Ied25519/sha512 SOURCES = curve25519-donna.c curve25519-donna-wrapper.cpp $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) ed25519/sha512/sha2big.c # Build rules generated by macros from common.mk: diff --git a/nacl/curve25519-donna-wrapper.cpp b/nacl/curve25519-donna-wrapper.cpp index 28087830..ba17e915 100644 --- a/nacl/curve25519-donna-wrapper.cpp +++ b/nacl/curve25519-donna-wrapper.cpp @@ -15,6 +15,7 @@ */ #include "curve25519-donna.h" +#include "ed25519/additions/curve_sigs.h" #include #include @@ -26,6 +27,37 @@ const unsigned char basepoint[32] = {9}; +template +class AutoArrayBufferObject { +private: + pp::VarArrayBuffer buf; + unsigned char* map; +public: + AutoArrayBufferObject(pp::Var v) : buf(v), map(NULL) {} + + unsigned char *Get() { + if (map) + return map; + + if (buf.is_null()) + return NULL; + if (Length > 0 && buf.ByteLength() != Length) + return NULL; + + map = static_cast(buf.Map()); + return map; + } + + long GetLength() { + return buf.is_null() ? -1 : buf.ByteLength(); + } + + ~AutoArrayBufferObject() { + if (map) + buf.Unmap(); + } +}; + class Curve25519Instance : public pp::Instance { public: explicit Curve25519Instance(PP_Instance instance) : pp::Instance(instance) {} @@ -35,37 +67,61 @@ public: return; // Go away broken client pp::VarDictionary dictionary(var_message); - pp::VarArrayBuffer privArrBuff(dictionary.Get("priv")); - if (privArrBuff.is_null() || privArrBuff.ByteLength() != 32) - return; // Go away broken client - unsigned char* priv = static_cast(privArrBuff.Map()); + std::string command = dictionary.Get("command").AsString(); - pp::VarArrayBuffer resBuffer(32); + pp::VarDictionary returnMessage; + + pp::VarArrayBuffer resBuffer(64); unsigned char* res = static_cast(resBuffer.Map()); - std::string command = dictionary.Get("command").AsString(); if (command == "bytesToPriv") { - memcpy(res, priv, 32); + AutoArrayBufferObject<32> priv(dictionary.Get("priv")); + if (!priv.Get()) + return; // Go away broken client + + memcpy(res, priv.Get(), 32); res[0] &= 248; res[31] &= 127; res[31] |= 64; } else if (command == "privToPub") { - curve25519_donna(res, priv, basepoint); + AutoArrayBufferObject<32> priv(dictionary.Get("priv")); + if (!priv.Get()) + return; // Go away broken client + + curve25519_donna(res, priv.Get(), basepoint); } else if (command == "ECDHE") { - pp::VarArrayBuffer pubArrBuff(dictionary.Get("pub")); - if (!pubArrBuff.is_null() && pubArrBuff.ByteLength() == 32) { - unsigned char* pub = static_cast(pubArrBuff.Map()); - curve25519_donna(res, priv, pub); - pubArrBuff.Unmap(); - } + AutoArrayBufferObject<32> priv(dictionary.Get("priv")); + AutoArrayBufferObject<32> pub(dictionary.Get("pub")); + if (!priv.Get() || !pub.Get()) + return; // Go away broken client + + curve25519_donna(res, priv.Get(), pub.Get()); + } else if (command == "Ed25519Sign") { + AutoArrayBufferObject<32> priv(dictionary.Get("priv")); + AutoArrayBufferObject<-1> msg(dictionary.Get("msg")); + if (!priv.Get() || !msg.Get()) + return; // Go away broken client + + curve25519_sign(res, priv.Get(), msg.Get(), msg.GetLength()); } resBuffer.Unmap(); - privArrBuff.Unmap(); - pp::VarDictionary returnMessage; + if (command != "Ed25519Verify") + returnMessage.Set("res", resBuffer); + else { + AutoArrayBufferObject<32> pub(dictionary.Get("pub")); + AutoArrayBufferObject<-1> msg(dictionary.Get("msg")); + AutoArrayBufferObject<64> sig(dictionary.Get("sig")); + if (!pub.Get() || !msg.Get() || !sig.Get()) + return; // Go away broken client + + bool res = curve25519_verify(sig.Get(), pub.Get(), msg.Get(), msg.GetLength()) == 0; + + returnMessage.Set("res", res); + } + returnMessage.Set("call_id", dictionary.Get("call_id").AsInt()); - returnMessage.Set("res", resBuffer); PostMessage(returnMessage); } }; diff --git a/nacl/curve25519-jni.c b/nacl/curve25519-jni.c deleted file mode 100644 index 305370ac..00000000 --- a/nacl/curve25519-jni.c +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (C) 2013-2014 Open Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include -#include "curve25519-donna.h" -#include "curve_sigs.h" - -JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePrivateKey - (JNIEnv *env, jclass clazz, jbyteArray random, jboolean ephemeral) -{ - uint8_t* privateKey = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0); - - privateKey[0] &= 248; - - if (ephemeral) { - privateKey[0] |= 1; - } - - privateKey[31] &= 127; - privateKey[31] |= 64; - - (*env)->ReleaseByteArrayElements(env, random, privateKey, 0); - - return random; -} - -JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePublicKey - (JNIEnv *env, jclass clazz, jbyteArray privateKey) -{ - static const uint8_t basepoint[32] = {9}; - - jbyteArray publicKey = (*env)->NewByteArray(env, 32); - uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); - uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); - - curve25519_donna(publicKeyBytes, privateKeyBytes, basepoint); - - (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); - (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); - - return publicKey; -} - -JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateAgreement - (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey) -{ - jbyteArray sharedKey = (*env)->NewByteArray(env, 32); - uint8_t* sharedKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, sharedKey, 0); - uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); - uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); - - curve25519_donna(sharedKeyBytes, privateKeyBytes, publicKeyBytes); - - (*env)->ReleaseByteArrayElements(env, sharedKey, sharedKeyBytes, 0); - (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); - (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); - - return sharedKey; -} - -JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature - (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray message) -{ - jbyteArray signature = (*env)->NewByteArray(env, 64); - uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0); - uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0); - uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0); - jsize messageLength = (*env)->GetArrayLength(env, message); - - curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength); - - (*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0); - (*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0); - (*env)->ReleaseByteArrayElements(env, message, messageBytes, 0); - - return signature; -} - -JNIEXPORT jboolean JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_verifySignature - (JNIEnv *env, jclass clazz, jbyteArray publicKey, jbyteArray message, jbyteArray signature) -{ - uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0); - uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0); - uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0); - jsize messageLength = (*env)->GetArrayLength(env, message); - - jboolean result = (curve25519_verify(signatureBytes, publicKeyBytes, messageBytes, messageLength) == 0); - - (*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0); - (*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0); - (*env)->ReleaseByteArrayElements(env, message, messageBytes, 0); - - return result; -} diff --git a/nacl/ed25519/additions/curve_sigs.h b/nacl/ed25519/additions/curve_sigs.h index 706f7db6..106bb194 100644 --- a/nacl/ed25519/additions/curve_sigs.h +++ b/nacl/ed25519/additions/curve_sigs.h @@ -2,6 +2,10 @@ #ifndef __CURVE_SIGS_H__ #define __CURVE_SIGS_H__ +#ifdef __cplusplus +extern "C" { +#endif + void curve25519_keygen(unsigned char* curve25519_pubkey_out, unsigned char* curve25519_privkey_in); @@ -22,4 +26,8 @@ int crypto_sign_modified( const unsigned char *sk ); +#ifdef __cplusplus +} +#endif + #endif diff --git a/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.deps b/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.deps index 9fb68883..ccffbfdc 100644 --- a/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.deps +++ b/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.deps @@ -1,6 +1,7 @@ # Updated by fix_deps.py pnacl/Debug/curve25519-donna-wrapper_pnacl.o: \ curve25519-donna-wrapper.cpp curve25519-donna.h \ + ed25519/additions/curve_sigs.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/cpp/instance.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_instance.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_macros.h \ @@ -34,6 +35,7 @@ pnacl/Debug/curve25519-donna-wrapper_pnacl.o: \ : curve25519-donna-wrapper.cpp: curve25519-donna.h: +ed25519/additions/curve_sigs.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/cpp/instance.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_instance.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_macros.h: diff --git a/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.o b/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.o index 4f1e391d..02e47962 100644 Binary files a/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.o and b/nacl/pnacl/Debug/curve25519-donna-wrapper_pnacl.o differ diff --git a/nacl/pnacl/Debug/curve25519.bc b/nacl/pnacl/Debug/curve25519.bc index 8fdc6832..714d293c 100755 Binary files a/nacl/pnacl/Debug/curve25519.bc and b/nacl/pnacl/Debug/curve25519.bc differ diff --git a/nacl/pnacl/Debug/curve25519.pexe b/nacl/pnacl/Debug/curve25519.pexe index db25148c..51e4cf45 100644 Binary files a/nacl/pnacl/Debug/curve25519.pexe and b/nacl/pnacl/Debug/curve25519.pexe differ diff --git a/nacl/pnacl/Debug/curve25519_arm.nexe b/nacl/pnacl/Debug/curve25519_arm.nexe index a0bb8de3..3b677230 100755 Binary files a/nacl/pnacl/Debug/curve25519_arm.nexe and b/nacl/pnacl/Debug/curve25519_arm.nexe differ diff --git a/nacl/pnacl/Debug/curve25519_x86_32.nexe b/nacl/pnacl/Debug/curve25519_x86_32.nexe index 848d13dd..e3a891ba 100755 Binary files a/nacl/pnacl/Debug/curve25519_x86_32.nexe and b/nacl/pnacl/Debug/curve25519_x86_32.nexe differ diff --git a/nacl/pnacl/Debug/curve25519_x86_64.nexe b/nacl/pnacl/Debug/curve25519_x86_64.nexe index 2447befb..158b8922 100755 Binary files a/nacl/pnacl/Debug/curve25519_x86_64.nexe and b/nacl/pnacl/Debug/curve25519_x86_64.nexe differ diff --git a/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.deps b/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.deps index 901d7dac..6a76f545 100644 --- a/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.deps +++ b/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.deps @@ -1,6 +1,7 @@ # Updated by fix_deps.py pnacl/Release/curve25519-donna-wrapper_pnacl.o: \ curve25519-donna-wrapper.cpp curve25519-donna.h \ + ed25519/additions/curve_sigs.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/cpp/instance.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_instance.h \ /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_macros.h \ @@ -34,6 +35,7 @@ pnacl/Release/curve25519-donna-wrapper_pnacl.o: \ : curve25519-donna-wrapper.cpp: curve25519-donna.h: +ed25519/additions/curve_sigs.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/cpp/instance.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_instance.h: /home/matt/nacl_sdk/pepper_31//include/ppapi/c/pp_macros.h: diff --git a/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.o b/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.o index eca15bfb..438d5999 100644 Binary files a/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.o and b/nacl/pnacl/Release/curve25519-donna-wrapper_pnacl.o differ diff --git a/nacl/pnacl/Release/curve25519.pexe b/nacl/pnacl/Release/curve25519.pexe index 06c993dc..e287554d 100644 Binary files a/nacl/pnacl/Release/curve25519.pexe and b/nacl/pnacl/Release/curve25519.pexe differ diff --git a/nacl/pnacl/Release/curve25519_unstripped.bc b/nacl/pnacl/Release/curve25519_unstripped.bc index 170fd3cf..e3fc8e29 100755 Binary files a/nacl/pnacl/Release/curve25519_unstripped.bc and b/nacl/pnacl/Release/curve25519_unstripped.bc differ diff --git a/nacl/pnacl/Release/curve25519_unstripped.pexe b/nacl/pnacl/Release/curve25519_unstripped.pexe index 06c993dc..e287554d 100644 Binary files a/nacl/pnacl/Release/curve25519_unstripped.pexe and b/nacl/pnacl/Release/curve25519_unstripped.pexe differ