#!/bin/zsh
set -e

echo "Creating tmpfs directories..."
for i in /usr/lib/gcc /usr/arm-none-eabi /usr/lib/python2.7; do
	mkdir -p $i
	mount -t tmpfs tmpfs $i
done

echo "Downloading and installing required packages..."
pacman -Sy arm-none-eabi-{gcc,binutils,newlib} git gcc make fakeroot python2 patch

echo "Creating symlinks required due to tmpfs..."
ln -s /usr/arm-none-eabi/bin/objcopy /usr/bin/arm-none-eabi-objcopy

echo "Patching makepkg to allow building as root..."
sed 's/EUID == 0/EUID == 1234/' -i.orig /usr/bin/makepkg

echo "Building and installing python2-pyusb"
mkdir python2-pyusb
cd python2-pyusb
cat >PKGBUILD <<__EOF__
# Maintainer: Nuno Araujo <nuno.araujo@russo79.com>
# Contributor: Limao Luo <luolimao+AUR@gmail.com>
# Contributor: Jason Giangrande <jgiangrande@clarku.edu>

_pkgname=pyusb
pkgname=python2-pyusb
pkgver=0.4.3
pkgrel=7
pkgdesc="A native Python module written in C which provides USB access."
arch=('i686' 'x86_64')
url="http://pyusb.berlios.de/"
license=('custom')
depends=('python2' 'libusb-compat')
makedepends=('python2-distribute')
conflicts=(\$_pkgname=\$pkgver)
provides=(\$_pkgname)
source=("http://downloads.sourceforge.net/project/\${_pkgname}/PyUSB%200.x/\$pkgver/\${_pkgname}-\$pkgver.tar.gz")
# Orig PKGBUILD had md5, changed to sha256 as md5 is broken
sha256sums=('3c08b292886b7001ab088345af4d0dfe3e7d37bfc4b2bdcd7edb564ea3ef04d5')

build() {
	cd \$srcdir/\$_pkgname-\$pkgver
	python2 setup.py build
}

package() {
	cd \$srcdir/\$_pkgname-\$pkgver
	python2 setup.py install -f --root="\$pkgdir"
	install -Dm644 LICENSE "\$pkgdir"/usr/share/licenses/\$pkgname/LICENSE
}
__EOF__
makepkg -s
pacman -U python2-pyusb-0.4.3-*.pkg.tar.xz
cd ..

echo "Building and installing python2-colorama..."
mkdir python2-colorama
cd python2-colorama
cat >PKGBUILD <<__EOF__
# Maintainer: Alexander Duscheleit <jinks@archlinux.us>
pkgname=python2-colorama
pkgver=0.3.2
pkgrel=1
pkgdesc="Python API for cross-platform colored terminal text."
arch=('any')
url="http://pypi.python.org/pypi/colorama"
license=('BSD')
depends=('python2')
source=(http://pypi.python.org/packages/source/c/colorama/colorama-\$pkgver.tar.gz)
# Orig PKGBUILD had md5, changed to sha256 as md5 is broken
sha256sums=('218862857d74ff781c2caf44629a7d72b88bbb8a2b0aa0f4f1eb8666f8305c11')

build() {
  cd "\$srcdir/colorama-\$pkgver"

  python2 setup.py build
}

package() {
  cd "\$srcdir/colorama-\$pkgver"

  python2 setup.py install --root=\$pkgdir --optimize=1
}

# vim:set ts=2 sw=2 et:
__EOF__
makepkg -s
pacman -U python2-colorama-0.3.2-*.pkg.tar.xz
cd ..

echo "Downloading Gnuk..."
git clone https://gitorious.org/gnuk/gnuk.git
cd gnuk
echo "Checking out release/1.1.4 tag..."
git checkout release/1.1.4
echo "Verifying Gnuk checkout..."
if [ "$(git rev-parse HEAD)" = "e7e8b9f5ca414a5c901f61b0f043c8da42414103" ]
then
	echo "Verification successful!"
else
	echo "Verification failed! Possible MITM!"
	exit 1
fi

echo "Patching Gnuk..."
patch -p1 <<__EOF__
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Mon, 9 Feb 2015 07:28:26 +0000 (+0900)
Subject: Fix the bug of EdDSA signing
X-Git-Url: http://git.gniibe.org/gitweb/?p=gnuk%2Fgnuk.git;a=commitdiff_plain;h=a9244d9b13319eadd7bfe96320b44a871f691120;hp=c268e59813cb1d25c76bdedc6bb7b2a160c0f530

Fix the bug of EdDSA signing
---

diff --git a/ChangeLog b/ChangeLog
index 50fba87..f9d1b37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-02-09  Niibe Yutaka  <gniibe@fsij.org>
+
+	* src/openpgp.c (cmd_pso): Fix eddsa. Use GPG_KEY_FOR_SIGNING.
+
 2014-12-15  Niibe Yutaka  <gniibe@fsij.org>
 
 	* VERSION: 1.1.4.
diff --git a/src/openpgp.c b/src/openpgp.c
index e1d1203..5976255 100644
--- a/src/openpgp.c
+++ b/src/openpgp.c
@@ -900,9 +900,9 @@ cmd_pso (void)
 
 	  res_APDU_size = EDDSA_SIGNATURE_LENGTH;
 	  r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
-				kd[GPG_KEY_FOR_AUTHENTICATION].data,
-				kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
-				kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
+				kd[GPG_KEY_FOR_SIGNING].data,
+				kd[GPG_KEY_FOR_SIGNING].data+32,
+				kd[GPG_KEY_FOR_SIGNING].pubkey);
 	  memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
 	}
     }
__EOF__
patch -p1 <<__EOF__
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Tue, 10 Feb 2015 00:58:45 +0000 (+0900)
Subject: Fix EdDSA signature counter
X-Git-Url: http://git.gniibe.org/gitweb/?p=gnuk%2Fgnuk.git;a=commitdiff_plain;h=0e510b32c1747a43f6504f68f5a2674aa7d7bbbd;hp=a9244d9b13319eadd7bfe96320b44a871f691120

Fix EdDSA signature counter
---

diff --git a/ChangeLog b/ChangeLog
index f9d1b37..b0aac5c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,14 @@
+2015-02-10  Niibe Yutaka  <gniibe@fsij.org>
+
+	* src/openpgp.c (cmd_pso): Fix counter update for EdDSA.  Thanks
+	to Jonathan Schleifer.
+
+	* src/call-rsa.c (rsa_sign): Don't set res_APDU_len.
+	(rsa_decrypt): Likewise, but get OUTPUT_LEN_P as an argument.
+
 2015-02-09  Niibe Yutaka  <gniibe@fsij.org>
 
-	* src/openpgp.c (cmd_pso): Fix eddsa. Use GPG_KEY_FOR_SIGNING.
+	* src/openpgp.c (cmd_pso): Fix EdDSA. Use GPG_KEY_FOR_SIGNING.
 
 2014-12-15  Niibe Yutaka  <gniibe@fsij.org>
 
diff --git a/src/call-rsa.c b/src/call-rsa.c
index c494156..6632c07 100644
--- a/src/call-rsa.c
+++ b/src/call-rsa.c
@@ -83,7 +83,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
     }
   else
     {
-      res_APDU_size = pubkey_len;
       DEBUG_INFO ("done.\r\n");
       GPG_SUCCESS ();
       return 0;
@@ -120,14 +119,13 @@ modulus_calc (const uint8_t *p, int len)
 
 int
 rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
-	     struct key_data *kd)
+	     struct key_data *kd, unsigned int *output_len_p)
 {
   mpi P1, Q1, H;
   int ret;
-  unsigned int output_len;
 
   DEBUG_INFO ("RSA decrypt:");
-  DEBUG_WORD ((uint32_t)&output_len);
+  DEBUG_WORD ((uint32_t)&ret);
 
   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
   mpi_init (&P1);  mpi_init (&Q1);  mpi_init (&H);
@@ -154,7 +152,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
     {
       DEBUG_INFO ("RSA decrypt ...");
       ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
-					 RSA_PRIVATE, &output_len, input,
+					 RSA_PRIVATE, output_len_p, input,
 					 output, MAX_RES_APDU_DATA_SIZE);
     }
 
@@ -167,7 +165,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
     }
   else
     {
-      res_APDU_size = output_len;
       DEBUG_INFO ("done.\r\n");
       GPG_SUCCESS ();
       return 0;
diff --git a/src/gnuk.h b/src/gnuk.h
index 63b4a76..cb58636 100644
--- a/src/gnuk.h
+++ b/src/gnuk.h
@@ -256,7 +256,8 @@ void put_binary (const char *s, int len);
 
 int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
 uint8_t *modulus_calc (const uint8_t *, int);
-int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
+int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *,
+		 unsigned int *);
 int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *);
 uint8_t *rsa_genkey (int);
 
diff --git a/src/openpgp.c b/src/openpgp.c
index 5976255..c3107a0 100644
--- a/src/openpgp.c
+++ b/src/openpgp.c
@@ -819,6 +819,7 @@ cmd_pso (void)
   int r = -1;
   int attr;
   int pubkey_len;
+  unsigned int result_len = 0;
 
   DEBUG_INFO (" - PSO: ");
   DEBUG_WORD ((uint32_t)&r);
@@ -855,13 +856,9 @@ cmd_pso (void)
 
 	  DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, pubkey_len);
 
+	  result_len = pubkey_len;
 	  r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
 			&kd[GPG_KEY_FOR_SIGNING], pubkey_len);
-	  if (r < 0)
-	    ac_reset_pso_cds ();
-	  else
-	    /* Success */
-	    gpg_increment_digital_signature_counter ();
 	}
       else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
 	{
@@ -873,19 +870,13 @@ cmd_pso (void)
 	      return;
 	    }
 
+	  result_len = ECDSA_SIGNATURE_LENGTH;
 	  if (attr == ALGO_NISTP256R1)
 	    r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
 				   kd[GPG_KEY_FOR_SIGNING].data);
 	  else			/* ALGO_SECP256K1 */
 	    r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
 				   kd[GPG_KEY_FOR_SIGNING].data);
-	  if (r < 0)
-	    ac_reset_pso_cds ();
-	  else
-	    {			/* Success */
-	      gpg_increment_digital_signature_counter ();
-	      res_APDU_size = ECDSA_SIGNATURE_LENGTH;
-	    }
 	}
       else if (attr == ALGO_ED25519)
 	{
@@ -898,13 +889,27 @@ cmd_pso (void)
 	      return;
 	    }
 
-	  res_APDU_size = EDDSA_SIGNATURE_LENGTH;
+	  result_len = EDDSA_SIGNATURE_LENGTH;
 	  r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
 				kd[GPG_KEY_FOR_SIGNING].data,
 				kd[GPG_KEY_FOR_SIGNING].data+32,
 				kd[GPG_KEY_FOR_SIGNING].pubkey);
 	  memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
 	}
+      else
+	{
+	  DEBUG_INFO ("unknown algo.");
+	  GPG_FUNCTION_NOT_SUPPORTED ();
+	  return;
+	}
+
+      if (r == 0)
+	{
+	  res_APDU_size = result_len;
+	  gpg_increment_digital_signature_counter ();
+	}
+      else   /* Failure */
+	ac_reset_pso_cds ();
     }
   else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
     {
@@ -931,7 +936,7 @@ cmd_pso (void)
 	      return;
 	    }
 	  r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
-			   &kd[GPG_KEY_FOR_DECRYPTION]);
+			   &kd[GPG_KEY_FOR_DECRYPTION], &result_len);
 	}
       else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
 	{
@@ -942,16 +947,23 @@ cmd_pso (void)
 	      return;
 	    }
 
+	  result_len = 65;
 	  if (attr == ALGO_NISTP256R1)
 	    r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data, res_APDU,
 				     kd[GPG_KEY_FOR_DECRYPTION].data);
 	  else
 	    r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data, res_APDU,
 				     kd[GPG_KEY_FOR_DECRYPTION].data);
-
-	  if (r == 0)
-	    res_APDU_size = 65;
 	}
+      else
+	{
+	  DEBUG_INFO ("unknown algo.");
+	  GPG_FUNCTION_NOT_SUPPORTED ();
+	  return;
+	}
+
+      if (r == 0)
+	res_APDU_size = result_len;
     }
 
   if (r < 0)
__EOF__

echo "Downloading chopstx..."
git clone https://gitorious.org/chopstx/chopstx.git
cd chopstx
echo "Checking out release/0.04 tag..."
git checkout release/0.04
echo "Verifying chopstx checkout..."
if [ "$(git rev-parse HEAD)" = "23893d9b73ebc28ff111d21827122677c27bee55" ]
then
	echo "Verification successful!"
else
	echo "Verification failed! Possible MITM!"
	exit 1
fi

echo "Configuring Gnuk..."
cd ../src
./configure --vidpid=234b:0000

echo "Building Gnuk..."
make
gnuk_dir=$PWD

cd ../tool
echo "Now cd to $PWD and run:"
echo "  python2 stlink2.py -u  # Unlock flash"
echo "  python2 stlink2.py ../src/build/gnuk.bin  # Flash firmware"
