[Gnuk-users] AES symmetric decryption support

NIIBE Yutaka gniibe at fsij.org
Tue Jun 30 08:12:24 UTC 2015


Hello,

To test development of GnuPG for OpenPGPcard 3.0 support, I
experimented following patch for AES decryption.  The feature
is very basic, it only does bare AES decryption (128-bit key
and decrypt 128-bit into 128-bit).

I don't know if this is useful.

I'm not sure if I will incorporate this feature into Gnuk.

=================================
diff --git a/src/gnuk.h b/src/gnuk.h
index e096f78..58e8713 100644
--- a/src/gnuk.h
+++ b/src/gnuk.h
@@ -320,7 +320,8 @@ extern uint8_t admin_authorized;
 #define NR_DO_KEYSTRING_PW1	0x11
 #define NR_DO_KEYSTRING_RC	0x12
 #define NR_DO_KEYSTRING_PW3	0x13
-#define NR_DO__LAST__		20   /* == 0x14 */
+#define NR_DO_AES_SECRET	0x14
+#define NR_DO__LAST__		21   /* == 0x15 */
 /* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte).  */
 /*
  * Representation of 14-bit counter:
diff --git a/src/openpgp-do.c b/src/openpgp-do.c
index 6d91b69..bbae281 100644
--- a/src/openpgp-do.c
+++ b/src/openpgp-do.c
@@ -1,7 +1,7 @@
 /*
  * openpgp-do.c -- OpenPGP card Data Objects (DO) handling
  *
- * Copyright (C) 2010, 2011, 2012, 2013, 2014
+ * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
  *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe at fsij.org>
  *
@@ -401,6 +401,7 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
 #define GPG_DO_KGTIME_DEC	0x00cf
 #define GPG_DO_KGTIME_AUT	0x00d0
 #define GPG_DO_RESETTING_CODE	0x00d3
+#define GPG_DO_AES_SECRET	0x00d5
 #define GPG_DO_KEY_IMPORT	0x3fff
 #define GPG_DO_LANGUAGE		0x5f2d
 #define GPG_DO_SEX		0x5f35
@@ -800,6 +801,22 @@ proc_resetting_code (const uint8_t *data, int len)
   return 1;
 }

+static int
+proc_aes_secret (const uint8_t *data, int len)
+{
+  DEBUG_INFO ("AES secret.\r\n");
+
+  if (len != 16)
+    {
+      DEBUG_INFO ("wrong length.\r\n");
+      return 0;
+    }
+  else
+    gpg_do_write_simple (NR_DO_AES_SECRET, data, len);
+
+  return 1;
+}
+
 static void
 encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
 {
@@ -1429,9 +1446,12 @@ gpg_do_table[] = {
   { GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
   { GPG_DO_DISCRETIONARY, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_discretionary },
   { GPG_DO_SS_TEMP, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ss_temp },
-  /* Simple data: write access only */
+  /* Pseudo DO WRITE */
   { GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
     proc_resetting_code },
+  /* Simple data: write access only */
+  { GPG_DO_AES_SECRET, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
+    proc_aes_secret },
   /* Compound data: Write access only */
   { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
     proc_key_import },
diff --git a/src/openpgp.c b/src/openpgp.c
index 9468ee7..00f58c6 100644
--- a/src/openpgp.c
+++ b/src/openpgp.c
@@ -35,6 +35,9 @@
 #include "sha256.h"
 #include "random.h"

+#include "polarssl/config.h"
+#include "polarssl/aes.h"
+
 static struct eventflag *openpgp_comm;

 #define ADMIN_PASSWD_MINLEN 8
@@ -915,12 +918,6 @@ cmd_pso (void)
     }
   else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
     {
-      attr = gpg_get_algo_attr (GPG_KEY_FOR_DECRYPTION);
-      pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_DECRYPTION,
-					       GPG_KEY_PUBLIC);
-
-      DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, pubkey_len);
-
       if (!ac_check_status (AC_OTHER_AUTHORIZED))
 	{
 	  DEBUG_INFO ("security error.");
@@ -928,6 +925,48 @@ cmd_pso (void)
 	  return;
 	}

+      if (len == 17 && apdu.cmd_apdu_data[0] == 0x02)
+	{ /* PSO:DECIPHER with AES symmetric key.  */
+	  const uint8_t *k = gpg_do_read_simple (NR_DO_AES_SECRET);
+	  aes_context aes;
+	  uint8_t output[16];
+	  int r;
+
+	  DEBUG_INFO ("AES decrypt.");
+	  if (k == NULL)
+	    {
+	      DEBUG_INFO ("No AES key.");
+	      GPG_CONDITION_NOT_SATISFIED ();
+	      return;
+	    }
+
+	  r = aes_setkey_dec (&aes, k, 128);
+	  if (r != 0)
+	    {
+	      DEBUG_INFO ("AES key error.");
+	      GPG_CONDITION_NOT_SATISFIED ();
+	      return;
+	    }
+
+	  r = aes_crypt_ecb (&aes, AES_DECRYPT, apdu.cmd_apdu_data + 1, output);
+	  if (r != 0)
+	    {
+	      DEBUG_INFO ("AES decrypt error.");
+	      GPG_ERROR();
+	      return;
+	    }
+
+	  memcpy (res_APDU, output, 16);
+	  res_APDU_size = 16;
+	  return;
+	}
+
+      attr = gpg_get_algo_attr (GPG_KEY_FOR_DECRYPTION);
+      pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_DECRYPTION,
+					       GPG_KEY_PUBLIC);
+
+      DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, pubkey_len);
+
       if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
 	{
 	  /* Skip padding 0x00 */
--



More information about the gnuk-users mailing list