[PATCH 1/3] Implement C_GenerateRandom.

Damien Goutte-Gattat dgouttegattat at incenp.org
Mon Apr 4 21:41:15 CEST 2016


> Here we trust that the server does not return more than requested.  In
> the interest of robustness it is probably best to check that.

You're right. Please find a modified patch below.

This version checks whether we got exactly the requested amount of
random bytes (no more, no less), and returns an error if that is not the
case.

Since the caller of C_GenerateRandom has no way of knowing how many
bytes were effectively obtained from the token, I think we should not
return OK unless we can provide him with exactly what he has asked.

-- >8 --
* src/agent.c (scute_agent_get_random, get_challenge_data_cb):
New functions.
* src/agent.h (scute_agent_get_random): New prototype.
* src/p11-generaterandom.c (C_GenerateRandom): Implement feature.

Signed-off-by: Damien Goutte-Gattat <dgouttegattat at incenp.org>
---
 src/agent.c              | 36 ++++++++++++++++++++++++++++++++++++
 src/agent.h              |  3 +++
 src/p11-generaterandom.c | 28 +++++++++++++++++++++++-----
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index b51dc7e..d2ca9b9 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -1281,6 +1281,42 @@ scute_agent_get_cert (int no, struct cert *cert)
   return 0;
 }
 
+struct random_request
+{
+    unsigned char *buffer;
+    size_t len;
+};
+
+gpg_error_t
+get_challenge_data_cb (void *opaque, const void *line, size_t len)
+{
+  struct random_request *request = opaque;
+
+  if ( len != request->len )
+    return gpg_error (GPG_ERR_INV_LENGTH);
+
+  memcpy (request->buffer, line, len);
+
+  return 0;
+}
+
+gpg_error_t
+scute_agent_get_random (unsigned char *data, size_t len)
+{
+    char command[16];
+    gpg_error_t err;
+    struct random_request request;
+
+    snprintf (command, sizeof(command), "SCD RANDOM %lu", len);
+
+    request.buffer = data;
+    request.len = len;
+    err = assuan_transact (agent_ctx, command, get_challenge_data_cb,
+                           &request, NULL, NULL, NULL, NULL);
+
+    return err;
+}
+
 
 void
 scute_agent_finalize (void)
diff --git a/src/agent.h b/src/agent.h
index 6ac479f..6f3f6df 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -113,4 +113,7 @@ gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted);
 /* Try to get certificate for key numer NO.  */
 gpg_error_t scute_agent_get_cert (int no, struct cert *cert);
 
+/* Get random bytes from the card. */
+gpg_error_t scute_agent_get_random (unsigned char *data, size_t len);
+
 #endif	/* AGENT_H */
diff --git a/src/p11-generaterandom.c b/src/p11-generaterandom.c
index f192e9d..e8b20d9 100644
--- a/src/p11-generaterandom.c
+++ b/src/p11-generaterandom.c
@@ -33,14 +33,32 @@
 
 #include "cryptoki.h"
 
+#include "locking.h"
+#include "slots.h"
+#include "agent.h"
+#include "error-mapping.h"
+
 
 CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)
      (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData,
       CK_ULONG ulRandomLen)
 {
-  /* FIXME: Implement me.  */
-  (void) hSession;
-  (void) pRandomData;
-  (void) ulRandomLen;
-  return CKR_FUNCTION_NOT_SUPPORTED;
+  CK_RV err;
+  slot_iterator_t slot;
+  session_iterator_t session;
+
+  if (pRandomData == NULL_PTR)
+    return CKR_ARGUMENTS_BAD;
+
+  err = scute_global_lock ();
+  if (err)
+    return err;
+
+  err = slots_lookup_session (hSession, &slot, &session);
+  if (!err)
+    err = scute_gpg_err_to_ck (scute_agent_get_random (pRandomData,
+                                                       ulRandomLen));
+
+  scute_global_unlock ();
+  return err;
 }
-- 
2.7.4




More information about the Gnupg-devel mailing list