[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