pk: Move s-expr creation for sign and encrypt to the modules.
authorWerner Koch <wk@gnupg.org>
Sat, 7 Sep 2013 08:06:46 +0000 (10:06 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 19 Sep 2013 14:43:33 +0000 (16:43 +0200)
* cipher/pubkey.c (pubkey_encrypt): Fold into gcry_pk_encrypt.
(pubkey_decrypt): Fold into gcry_pk_decrypt.
(pubkey_sign): Fold into gcry_pk_sign.
(pubkey_verify): Fold into gcry_pk_verify.
(octet_string_from_mpi): Make it a wrapper and factor code out to ...
* mpi/mpicoder.c (_gcry_mpi_to_octet_string): New function.

* src/cipher.h (PUBKEY_FLAG_FIXEDLEN): New.
* cipher/pubkey.c (sexp_data_to_mpi): Set flag for some encodings.
(gcry_pk_encrypt): Simply by moving the s-expr generation to the modules.
(gcry_pk_sign): Ditto.
* cipher/dsa.c (dsa_sign): Create s-expr.
* cipher/elgamal.c (elg_encrypt, elg_sign): Ditto.
* cipher/rsa.c (rsa_encrypt, rsa_sign): Ditto.
* cipher/ecc.c (ecc_sign, ecc_encrypt_raw): Ditto.
(ecdsa_names): Add "eddsa".
* tests/t-ed25519.c (one_test): Expect "eddsa" token.

Signed-off-by: Werner Koch <wk@gnupg.org>
cipher/dsa.c
cipher/ecc.c
cipher/elgamal.c
cipher/pubkey.c
cipher/rsa.c
mpi/mpicoder.c
src/cipher-proto.h
src/cipher.h
src/mpi.h
tests/t-ed25519.c

index ca9a4f6..13a4fc2 100644 (file)
@@ -974,11 +974,12 @@ dsa_check_secret_key (int algo, gcry_mpi_t *skey)
 
 
 static gcry_err_code_t
-dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+dsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
           int flags, int hashalgo)
 {
   gcry_err_code_t rc;
   DSA_secret_key sk;
+  gcry_mpi_t r, s;
 
   (void)algo;
   (void)flags;
@@ -995,9 +996,15 @@ dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
       sk.g = skey[2];
       sk.y = skey[3];
       sk.x = skey[4];
-      resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p));
-      resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p));
-      rc = sign (resarr[0], resarr[1], data, &sk, flags, hashalgo);
+      r = mpi_alloc (mpi_get_nlimbs (sk.p));
+      s = mpi_alloc (mpi_get_nlimbs (sk.p));
+      rc = sign (r, s, data, &sk, flags, hashalgo);
+      if (!rc)
+        rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                             "(sig-val(dsa(r%M)(s%M)))",
+                                             r, s));
+      mpi_free (r);
+      mpi_free (s);
     }
   return rc;
 }
index 66cd342..b7d6239 100644 (file)
@@ -1375,11 +1375,12 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey)
 
 
 static gcry_err_code_t
-ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+ecc_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
           int flags, int hashalgo)
 {
-  gpg_err_code_t err;
+  gpg_err_code_t rc;
   ECC_secret_key sk;
+  gcry_mpi_t r, s;
 
   (void)algo;
 
@@ -1397,16 +1398,17 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
   sk.Q.x = NULL;
   sk.Q.y = NULL;
   sk.Q.z = NULL;
-  err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
-  if (err)
+  rc = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
+  if (rc)
     {
       point_free (&sk.E.G);
-      return err;
+      return rc;
     }
   sk.E.n = skey[4];
 
-  resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
-  resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+  r = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+  s = mpi_alloc (mpi_get_nlimbs (sk.E.p));
+
   {
     const unsigned char *buf;
     unsigned int n;
@@ -1415,35 +1417,42 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
     buf = gcry_mpi_get_opaque (skey[6], &n);
     if (!buf)
-      err = GPG_ERR_INV_OBJ;
+      rc = GPG_ERR_INV_OBJ;
     else
       {
         n = (n + 7)/8;
         sk.d = NULL;
-        err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
-        if (!err)
+        rc = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
+        if (!rc)
           {
             if ((flags & PUBKEY_FLAG_EDDSA))
-              err = sign_eddsa (data, &sk, resarr[0], resarr[1],
-                                hashalgo, skey[5]);
+              {
+                rc = sign_eddsa (data, &sk, r, s, hashalgo, skey[5]);
+                if (!rc)
+                  rc = gcry_err_code (gcry_sexp_build
+                                      (r_result, NULL,
+                                       "(sig-val(eddsa(r%M)(s%M)))", r, s));
+              }
             else
-              err = sign_ecdsa (data, &sk, resarr[0], resarr[1],
-                                flags, hashalgo);
+              {
+                rc = sign_ecdsa (data, &sk, r, s, flags, hashalgo);
+                if (!rc)
+                  rc = gcry_err_code (gcry_sexp_build
+                                      (r_result, NULL,
+                                       "(sig-val(ecdsa(r%M)(s%M)))", r, s));
+              }
             gcry_mpi_release (sk.d);
             sk.d = NULL;
           }
       }
   }
-  if (err)
-    {
-      mpi_free (resarr[0]);
-      mpi_free (resarr[1]);
-      resarr[0] = NULL; /* Mark array as released.  */
-    }
+
+  mpi_free (r);
+  mpi_free (s);
   point_free (&sk.E.G);
   if (sk.Q.x)
     point_free (&sk.Q);
-  return err;
+  return rc;
 }
 
 
@@ -1544,9 +1553,9 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
  * ecc_encrypt_raw description:
  *   input:
  *     data[0] : private scalar (k)
- *   output:
- *     result[0] : shared point (kdG)
- *     result[1] : generated ephemeral public key (kG)
+ *   output: A new S-expression with the parameters:
+ *     s : shared point (kdG)
+ *     e : generated ephemeral public key (kG)
  *
  * ecc_decrypt_raw description:
  *   input:
@@ -1555,13 +1564,13 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
  *     result[0] : shared point (kdG)
  */
 static gcry_err_code_t
-ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
+ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k,
                  gcry_mpi_t *pkey, int flags)
 {
+  gpg_err_code_t rc;
   ECC_public_key pk;
   mpi_ec_t ctx;
-  gcry_mpi_t result[2];
-  int err;
+  gcry_mpi_t s, e;
 
   (void)algo;
   (void)flags;
@@ -1575,24 +1584,26 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
   pk.E.a = pkey[1];
   pk.E.b = pkey[2];
   point_init (&pk.E.G);
-  err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
-  if (err)
+  rc = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
+  if (rc)
     {
       point_free (&pk.E.G);
-      return err;
+      return rc;
     }
   pk.E.n = pkey[4];
   point_init (&pk.Q);
-  err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
-  if (err)
+  rc = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
+  if (rc)
     {
       point_free (&pk.E.G);
       point_free (&pk.Q);
-      return err;
+      return rc;
     }
 
   ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect,
                                      pk.E.p, pk.E.a, pk.E.b);
+  s = mpi_alloc (mpi_get_nlimbs (pk.E.p));
+  e = mpi_alloc (mpi_get_nlimbs (pk.E.p));
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
   {
@@ -1609,16 +1620,14 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
-
-    result[0] = _gcry_ecc_ec2os (x, y, pk.E.p);
+    s = _gcry_ecc_ec2os (x, y, pk.E.p);
 
     /* R = kG */
     _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
-
-    result[1] = _gcry_ecc_ec2os (x, y, pk.E.p);
+    e = _gcry_ecc_ec2os (x, y, pk.E.p);
 
     mpi_free (x);
     mpi_free (y);
@@ -1630,18 +1639,13 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
   point_free (&pk.E.G);
   point_free (&pk.Q);
 
-  if (!result[0] || !result[1])
-    {
-      mpi_free (result[0]);
-      mpi_free (result[1]);
-      return GPG_ERR_ENOMEM;
-    }
-
-  /* Success.  */
-  resarr[0] = result[0];
-  resarr[1] = result[1];
+  rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                       "(enc-val(ecdh(s%m)(e%m)))",
+                                       s, e));
+  mpi_free (s);
+  mpi_free (e);
 
-  return 0;
+  return rc;
 }
 
 /*  input:
@@ -1991,6 +1995,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 static const char *ecdsa_names[] =
   {
     "ecdsa",
+    "eddsa",
     "ecc",
     NULL,
   };
index 65448e0..447d089 100644 (file)
@@ -705,27 +705,33 @@ elg_check_secret_key (int algo, gcry_mpi_t *skey)
 
 
 static gcry_err_code_t
-elg_encrypt (int algo, gcry_mpi_t *resarr,
+elg_encrypt (int algo, gcry_sexp_t *r_result,
              gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
+  gcry_err_code_t rc;
   ELG_public_key pk;
+  gcry_mpi_t a, b;
 
   (void)algo;
   (void)flags;
 
   if ((! data) || (! pkey[0]) || (! pkey[1]) || (! pkey[2]))
-    err = GPG_ERR_BAD_MPI;
+    rc = GPG_ERR_BAD_MPI;
   else
     {
       pk.p = pkey[0];
       pk.g = pkey[1];
       pk.y = pkey[2];
-      resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.p));
-      resarr[1] = mpi_alloc (mpi_get_nlimbs (pk.p));
-      do_encrypt (resarr[0], resarr[1], data, &pk);
+      a = mpi_alloc (mpi_get_nlimbs (pk.p));
+      b = mpi_alloc (mpi_get_nlimbs (pk.p));
+      do_encrypt (a, b, data, &pk);
+      rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                           "(enc-val(elg(a%m)(b%m)))",
+                                           a, b));
+      mpi_free (a);
+      mpi_free (b);
     }
-  return err;
+  return rc;
 }
 
 
@@ -756,11 +762,12 @@ elg_decrypt (int algo, gcry_mpi_t *result,
 
 
 static gcry_err_code_t
-elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+elg_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
           int flags, int hashalgo)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
+  gcry_err_code_t rc;
   ELG_secret_key sk;
+  gcry_mpi_t r, s;
 
   (void)algo;
   (void)flags;
@@ -771,19 +778,24 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
   if ((! data)
       || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
-    err = GPG_ERR_BAD_MPI;
+    rc = GPG_ERR_BAD_MPI;
   else
     {
       sk.p = skey[0];
       sk.g = skey[1];
       sk.y = skey[2];
       sk.x = skey[3];
-      resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p));
-      resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p));
-      sign (resarr[0], resarr[1], data, &sk);
+      r = mpi_alloc (mpi_get_nlimbs (sk.p));
+      s = mpi_alloc (mpi_get_nlimbs (sk.p));
+      sign (r, s, data, &sk);
+      rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                           "(sig-val(elg(r%M)(s%M)))",
+                                           r, s));
+      mpi_free (r);
+      mpi_free (s);
     }
 
-  return err;
+  return rc;
 }
 
 
index c755729..dc56cc3 100644 (file)
 #include "pubkey-internal.h"
 
 
-static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
-                                       gcry_mpi_t *data, gcry_mpi_t *skey,
-                                       int flags);
-static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
-                                    gcry_mpi_t hash, gcry_mpi_t *skey,
-                                    struct pk_encoding_ctx *ctx);
-static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
-                                      gcry_mpi_t *data, gcry_mpi_t *pkey,
-                                      struct pk_encoding_ctx *ctx);
-
-
 /* This is the list of the public-key algorithms included in
    Libgcrypt.  */
 static gcry_pk_spec_t *pubkey_list[] =
@@ -308,161 +297,6 @@ pubkey_check_secret_key (int algo, gcry_mpi_t *skey)
 }
 
 
-/****************
- * This is the interface to the public key encryption.  Encrypt DATA
- * with PKEY and put it into RESARR which should be an array of MPIs
- * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
- * check with pubkey_get_nenc() )
- */
-static gcry_err_code_t
-pubkey_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
-                gcry_mpi_t *pkey, int flags)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec;
-  int i;
-
-  /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as
-     an extra failsafe protection we explicitly test for fips mode
-     here. */
-  if (DBG_CIPHER && !fips_mode ())
-    {
-      log_debug ("pubkey_encrypt: algo=%d\n", algo);
-      for(i = 0; i < pubkey_get_npkey (algo); i++)
-       log_mpidump ("  pkey", pkey[i]);
-      log_mpidump ("  data", data);
-    }
-
-  spec = spec_from_algo (algo);
-  if (spec && spec->encrypt)
-    rc = spec->encrypt (algo, resarr, data, pkey, flags);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  if (!rc && DBG_CIPHER && !fips_mode ())
-    {
-      for(i = 0; i < pubkey_get_nenc (algo); i++)
-       log_mpidump("  encr", resarr[i] );
-    }
-  return rc;
-}
-
-
-/****************
- * This is the interface to the public key decryption.
- * ALGO gives the algorithm to use and this implicitly determines
- * the size of the arrays.
- * result is a pointer to a mpi variable which will receive a
- * newly allocated mpi or NULL in case of an error.
- */
-static gcry_err_code_t
-pubkey_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
-                gcry_mpi_t *skey, int flags)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec;
-  int i;
-
-  *result = NULL; /* So the caller can always do a mpi_free.  */
-  if (DBG_CIPHER && !fips_mode ())
-    {
-      log_debug ("pubkey_decrypt: algo=%d\n", algo);
-      for(i = 0; i < pubkey_get_nskey (algo); i++)
-       log_mpidump ("  skey", skey[i]);
-      for(i = 0; i < pubkey_get_nenc (algo); i++)
-       log_mpidump ("  data", data[i]);
-    }
-
-  spec = spec_from_algo (algo);
-  if (spec && spec->decrypt)
-    rc = spec->decrypt (algo, result, data, skey, flags);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  if (!rc && DBG_CIPHER && !fips_mode ())
-    log_mpidump (" plain", *result);
-
-  return rc;
-}
-
-
-/****************
- * This is the interface to the public key signing.
- * Sign data with skey and put the result into resarr which
- * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
- * algorithm allows this - check with pubkey_get_nsig() )
- */
-static gcry_err_code_t
-pubkey_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
-             gcry_mpi_t *skey, struct pk_encoding_ctx *ctx)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec;
-  int i;
-
-  if (DBG_CIPHER && !fips_mode ())
-    {
-      log_debug ("pubkey_sign: algo=%d\n", algo);
-      for(i = 0; i < pubkey_get_nskey (algo); i++)
-       log_mpidump ("  skey", skey[i]);
-      log_mpidump("  data", data );
-    }
-
-  spec = spec_from_algo (algo);
-  if (spec && spec->sign)
-    rc = spec->sign (algo, resarr, data, skey, ctx->flags, ctx->hash_algo);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  if (!rc && DBG_CIPHER && !fips_mode ())
-    for (i = 0; i < pubkey_get_nsig (algo); i++)
-      log_mpidump ("   sig", resarr[i]);
-
-  return rc;
-}
-
-
-/****************
- * Verify a public key signature.
- * Return 0 if the signature is good
- */
-static gcry_err_code_t
-pubkey_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
-               gcry_mpi_t *pkey, struct pk_encoding_ctx *ctx)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec;
-  int i;
-
-  if (DBG_CIPHER && !fips_mode ())
-    {
-      log_debug ("pubkey_verify: algo=%d\n", algo);
-      for (i = 0; i < pubkey_get_npkey (algo); i++)
-       log_mpidump ("  pkey", pkey[i]);
-      for (i = 0; i < pubkey_get_nsig (algo); i++)
-       log_mpidump ("   sig", data[i]);
-      log_mpidump ("  hash", hash);
-    }
-
-  spec = spec_from_algo (algo);
-  if (spec && spec->verify)
-    rc = spec->verify (algo, hash, data, pkey,
-                       ctx->verify_cmp, ctx, ctx->flags, ctx->hash_algo);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  return rc;
-}
-
-
 /* Turn VALUE into an octet string and store it in an allocated buffer
    at R_FRAME or - if R_RAME is NULL - copy it into the caller
    provided buffer SPACE; either SPACE or R_FRAME may be used.  If
@@ -474,50 +308,7 @@ static gpg_err_code_t
 octet_string_from_mpi (unsigned char **r_frame, void *space,
                        gcry_mpi_t value, size_t nbytes)
 {
-  gpg_err_code_t rc;
-  size_t nframe, noff, n;
-  unsigned char *frame;
-
-  if (!r_frame == !space)
-    return GPG_ERR_INV_ARG;  /* Only one may be used.  */
-
-  if (r_frame)
-    *r_frame = NULL;
-
-  rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
-                                      NULL, 0, &nframe, value));
-  if (rc)
-    return rc;
-  if (nframe > nbytes)
-    return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES.  */
-
-  noff = (nframe < nbytes)? nbytes - nframe : 0;
-  n = nframe + noff;
-  if (space)
-    frame = space;
-  else
-    {
-      frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n);
-      if (!frame)
-        {
-          rc = gpg_err_code_from_syserror ();
-          return rc;
-        }
-    }
-  if (noff)
-    memset (frame, 0, noff);
-  nframe += noff;
-  rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
-                                      frame+noff, nframe-noff, NULL, value));
-  if (rc)
-    {
-      gcry_free (frame);
-      return rc;
-    }
-
-  if (r_frame)
-    *r_frame = frame;
-  return 0;
+  return _gcry_mpi_to_octet_string (r_frame, space, value, nbytes);
 }
 
 
@@ -2210,13 +2001,22 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
               }
             else if ( n == 5 && !memcmp (s, "pkcs1", 5)
                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              ctx->encoding = PUBKEY_ENC_PKCS1;
+              {
+                ctx->encoding = PUBKEY_ENC_PKCS1;
+                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+              }
             else if ( n == 4 && !memcmp (s, "oaep", 4)
                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              ctx->encoding = PUBKEY_ENC_OAEP;
+              {
+                ctx->encoding = PUBKEY_ENC_OAEP;
+                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+              }
             else if ( n == 3 && !memcmp (s, "pss", 3)
                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              ctx->encoding = PUBKEY_ENC_PSS;
+              {
+                ctx->encoding = PUBKEY_ENC_PSS;
+                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
+              }
            else if (n == 11 && ! memcmp (s, "no-blinding", 11))
              parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
             else
@@ -2646,11 +2446,12 @@ init_encoding_ctx (struct pk_encoding_ctx *ctx, enum pk_operation op,
 gcry_error_t
 gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
 {
-  gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
-  const char *algo_name, *algo_elems;
-  struct pk_encoding_ctx ctx;
   gcry_err_code_t rc;
+  gcry_mpi_t *pkey = NULL;
+  gcry_mpi_t data = NULL;
+  struct pk_encoding_ctx ctx;
   gcry_pk_spec_t *spec = NULL;
+  int i;
 
   *r_ciph = NULL;
 
@@ -2661,116 +2462,43 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
 
   gcry_assert (spec);
 
-  /* If aliases for the algorithm name exists, take the first one
-     instead of the regular name to adhere to SPKI conventions.  We
-     assume that the first alias name is the lowercase version of the
-     regular one.  This change is required for compatibility with
-     1.1.12 generated S-expressions. */
-  algo_name = spec->aliases? *spec->aliases : NULL;
-  if (!algo_name || !*algo_name)
-    algo_name = spec->name;
-
-  algo_elems = spec->elements_enc;
-
   /* Get the stuff we want to encrypt. */
   init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey));
   rc = sexp_data_to_mpi (s_data, &data, &ctx);
   if (rc)
     goto leave;
 
-  /* Now we can encrypt DATA to CIPH. */
-  ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
-  if (!ciph)
+  /* In fips mode DBG_CIPHER will never evaluate to true but as an
+     extra failsafe protection we explicitly test for fips mode
+     here. */
+  if (DBG_CIPHER && !fips_mode ())
     {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
+      log_debug ("pubkey_encrypt: algo=%d\n", spec->algo);
+      for(i = 0; i < pubkey_get_npkey (spec->algo); i++)
+       log_mpidump ("  pkey", pkey[i]);
+      log_mpidump ("  data", data);
     }
-  rc = pubkey_encrypt (spec->algo, ciph, data, pkey, ctx.flags);
-  mpi_free (data);
-  data = NULL;
-  if (rc)
-    goto leave;
 
-  /* We did it.  Now build the return list */
-  if (ctx.encoding == PUBKEY_ENC_OAEP
-      || ctx.encoding == PUBKEY_ENC_PKCS1)
-    {
-      /* We need to make sure to return the correct length to avoid
-         problems with missing leading zeroes.  We know that this
-         encoding does only make sense with RSA thus we don't need to
-         build the S-expression on the fly.  */
-      unsigned char *em;
-      size_t emlen = (ctx.nbits+7)/8;
-
-      rc = octet_string_from_mpi (&em, NULL, ciph[0], emlen);
-      if (rc)
-        goto leave;
-      rc = gcry_err_code (gcry_sexp_build (r_ciph, NULL,
-                                           "(enc-val(%s(a%b)))",
-                                           algo_name, (int)emlen, em));
-      gcry_free (em);
-      if (rc)
-        goto leave;
-    }
+  if (spec->encrypt)
+    rc = spec->encrypt (spec->algo, r_ciph, data, pkey, ctx.flags);
   else
-    {
-      char *string, *p;
-      int i;
-      size_t nelem = strlen (algo_elems);
-      size_t needed = 19 + strlen (algo_name) + (nelem * 5);
-      void **arg_list;
-
-      /* Build the string.  */
-      string = p = gcry_malloc (needed);
-      if (!string)
-        {
-          rc = gpg_err_code_from_syserror ();
-          goto leave;
-        }
-      p = stpcpy ( p, "(enc-val(" );
-      p = stpcpy ( p, algo_name );
-      for (i=0; algo_elems[i]; i++ )
-        {
-          *p++ = '(';
-          *p++ = algo_elems[i];
-          p = stpcpy ( p, "%m)" );
-        }
-      strcpy ( p, "))" );
-
-      /* And now the ugly part: We don't have a function to pass an
-       * array to a format string, so we have to do it this way :-(.  */
-      /* FIXME: There is now such a format specifier, so we can
-         change the code to be more clear. */
-      arg_list = malloc (nelem * sizeof *arg_list);
-      if (!arg_list)
-        {
-          rc = gpg_err_code_from_syserror ();
-          goto leave;
-        }
+    rc = GPG_ERR_NOT_IMPLEMENTED;
 
-      for (i = 0; i < nelem; i++)
-        arg_list[i] = ciph + i;
 
-      rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
-      free (arg_list);
-      if (rc)
-        BUG ();
-      gcry_free (string);
-    }
+  /* if (DBG_CIPHER && !fips_mode ()) */
+  /*   { */
+  /*     for (i = 0; i < pubkey_get_nenc (spec->algo); i++) */
+  /*       log_mpidump ("  encr", ciph[i]); */
+  /*   } */
 
  leave:
+  mpi_free (data);
   if (pkey)
     {
       release_mpi_array (pkey);
       gcry_free (pkey);
     }
 
-  if (ciph)
-    {
-      release_mpi_array (ciph);
-      gcry_free (ciph);
-    }
-
   gcry_free (ctx.label);
 
   return gcry_error (rc);
@@ -2814,16 +2542,17 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
   gcry_mpi_t plain = NULL;
   unsigned char *unpad = NULL;
   size_t unpadlen = 0;
+  int i;
   int modern, flags;
   struct pk_encoding_ctx ctx;
+  gcry_pk_spec_t *spec = NULL;
   gcry_pk_spec_t *spec_enc = NULL;
-  gcry_pk_spec_t *spec_key = NULL;
 
   *r_plain = NULL;
   ctx.label = NULL;
 
   rc = sexp_to_key (s_skey, 1, GCRY_PK_USAGE_ENCR, NULL,
-                    &skey, &spec_key, NULL);
+                    &skey, &spec, NULL);
   if (rc)
     goto leave;
 
@@ -2832,16 +2561,31 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
   if (rc)
     goto leave;
 
-  if (spec_key->algo != spec_enc->algo)
+  if (spec->algo != spec_enc->algo)
     {
       rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */
       goto leave;
     }
 
-  rc = pubkey_decrypt (spec_key->algo, &plain, data, skey, flags);
+  if (DBG_CIPHER && !fips_mode ())
+    {
+      log_debug ("gcry_pk_decrypt: algo=%d\n", spec->algo);
+      for(i = 0; i < pubkey_get_nskey (spec->algo); i++)
+       log_mpidump ("  skey", skey[i]);
+      for(i = 0; i < pubkey_get_nenc (spec->algo); i++)
+       log_mpidump ("  data", data[i]);
+    }
+
+  if (spec->decrypt)
+    rc = spec->decrypt (spec->algo, &plain, data, skey, flags);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
   if (rc)
     goto leave;
 
+  if (DBG_CIPHER && !fips_mode ())
+    log_mpidump (" plain", plain);
+
   /* Do un-padding if necessary. */
   switch (ctx.encoding)
     {
@@ -2931,9 +2675,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
 {
   gcry_mpi_t *skey = NULL;
   gcry_mpi_t hash = NULL;
-  gcry_mpi_t *result = NULL;
   gcry_pk_spec_t *spec = NULL;
-  const char *algo_name, *algo_elems;
   struct pk_encoding_ctx ctx;
   int i;
   int is_ecc;
@@ -2947,11 +2689,6 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
     goto leave;
 
   gcry_assert (spec);
-  algo_name = spec->aliases? *spec->aliases : NULL;
-  if (!algo_name || !*algo_name)
-    algo_name = spec->name;
-
-  algo_elems = spec->elements_sig;
 
   /* Get the stuff we want to sign.  Note that pk_get_nbits does also
      work on a private key.  We don't need the number of bits for ECC
@@ -2962,81 +2699,26 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
   if (rc)
     goto leave;
 
-  result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
-  if (!result)
+  if (DBG_CIPHER && !fips_mode ())
     {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
+      log_debug ("gcry_pk_sign: algo=%d\n", spec->algo);
+      for(i = 0; i < pubkey_get_nskey (spec->algo); i++)
+        log_mpidump ("  skey", skey[i]);
+      log_mpidump("  data", hash);
     }
-  rc = pubkey_sign (spec->algo, result, hash, skey, &ctx);
-  if (rc)
-    goto leave;
 
-  if (ctx.encoding == PUBKEY_ENC_PSS
-      || ctx.encoding == PUBKEY_ENC_PKCS1)
-    {
-      /* We need to make sure to return the correct length to avoid
-         problems with missing leading zeroes.  We know that this
-         encoding does only make sense with RSA thus we don't need to
-         build the S-expression on the fly.  */
-      unsigned char *em;
-      size_t emlen = (ctx.nbits+7)/8;
-
-      rc = octet_string_from_mpi (&em, NULL, result[0], emlen);
-      if (rc)
-        goto leave;
-      rc = gcry_err_code (gcry_sexp_build (r_sig, NULL,
-                                           "(sig-val(%s(s%b)))",
-                                           algo_name, (int)emlen, em));
-      gcry_free (em);
-      if (rc)
-        goto leave;
-    }
+  if (spec->sign)
+    rc = spec->sign (spec->algo, r_sig, hash, skey, ctx.flags, ctx.hash_algo);
   else
-    {
-      /* General purpose output encoding.  Do it on the fly.  */
-      char *string, *p;
-      size_t nelem, needed = strlen (algo_name) + 20;
-      void **arg_list;
-
-      nelem = strlen (algo_elems);
-
-      /* Count elements, so that we can allocate enough space. */
-      needed += 10 * nelem;
-
-      /* Build the string. */
-      string = p = gcry_malloc (needed);
-      if (!string)
-        {
-          rc = gpg_err_code_from_syserror ();
-          goto leave;
-        }
-      p = stpcpy (p, "(sig-val(");
-      p = stpcpy (p, algo_name);
-      for (i = 0; algo_elems[i]; i++)
-        {
-          *p++ = '(';
-          *p++ = algo_elems[i];
-          p = stpcpy (p, "%M)");
-        }
-      strcpy (p, "))");
-
-      arg_list = malloc (nelem * sizeof *arg_list);
-      if (!arg_list)
-        {
-          rc = gpg_err_code_from_syserror ();
-          goto leave;
-        }
+    rc = GPG_ERR_NOT_IMPLEMENTED;
 
-      for (i = 0; i < nelem; i++)
-        arg_list[i] = result + i;
+  if (rc)
+    goto leave;
 
-      rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
-      free (arg_list);
-      if (rc)
-        BUG ();
-      gcry_free (string);
-    }
+  /* Fixme: To print the result we need to print an sexp.  */
+  /* if (!rc && DBG_CIPHER && !fips_mode ()) */
+  /*   for (i = 0; i < pubkey_get_nsig (algo); i++) */
+  /*     log_mpidump ("   sig", resarr[i]); */
 
  leave:
   if (skey)
@@ -3054,14 +2736,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
       gcry_free (skey);
     }
 
-  if (hash)
-    mpi_free (hash);
-
-  if (result)
-    {
-      release_mpi_array (result);
-      gcry_free (result);
-    }
+  mpi_free (hash);
 
   return gcry_error (rc);
 }
@@ -3078,15 +2753,16 @@ gcry_error_t
 gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
 {
   gcry_err_code_t rc;
-  gcry_pk_spec_t *spec_key = NULL;
+  gcry_pk_spec_t *spec = NULL;
   gcry_pk_spec_t *spec_sig = NULL;
   gcry_mpi_t *pkey = NULL;
   gcry_mpi_t hash = NULL;
   gcry_mpi_t *sig = NULL;
   struct pk_encoding_ctx ctx;
+  int i;
 
   rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_SIGN, NULL,
-                    &pkey, &spec_key, NULL);
+                    &pkey, &spec, NULL);
   if (rc)
     goto leave;
 
@@ -3104,13 +2780,28 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
   /* Fixme: Check that the algorithm of S_SIG is compatible to the one
      of S_PKEY.  */
 
-  if (spec_key->algo != spec_sig->algo)
+  if (spec->algo != spec_sig->algo)
     {
       rc = GPG_ERR_CONFLICT;
       goto leave;
     }
 
-  rc = pubkey_verify (spec_key->algo, hash, sig, pkey, &ctx);
+  if (DBG_CIPHER && !fips_mode ())
+    {
+      log_debug ("gcry_pk_verify: algo=%d\n", spec->algo);
+      for (i = 0; i < pubkey_get_npkey (spec->algo); i++)
+        log_mpidump ("  pkey", pkey[i]);
+      for (i = 0; i < pubkey_get_nsig (spec->algo); i++)
+        log_mpidump ("   sig", sig[i]);
+      log_mpidump ("  hash", hash);
+      }
+
+  if (spec->verify)
+    rc = spec->verify (spec->algo, hash, sig, pkey,
+                       ctx.verify_cmp, &ctx, ctx.flags, ctx.hash_algo);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
+
 
  leave:
   if (pkey)
index e495cd8..91349db 100644 (file)
@@ -893,20 +893,43 @@ rsa_check_secret_key (int algo, gcry_mpi_t *skey)
 
 
 static gcry_err_code_t
-rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data,
              gcry_mpi_t *pkey, int flags)
 {
+  gpg_err_code_t rc;
   RSA_public_key pk;
+  gcry_mpi_t result;
 
   (void)algo;
   (void)flags;
 
   pk.n = pkey[0];
   pk.e = pkey[1];
-  resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n));
-  public (resarr[0], data, &pk);
+  result = mpi_alloc (mpi_get_nlimbs (pk.n));
+  public (result, data, &pk);
+  if ((flags & PUBKEY_FLAG_FIXEDLEN))
+    {
+      /* We need to make sure to return the correct length to avoid
+         problems with missing leading zeroes.  */
+      unsigned char *em;
+      size_t emlen = (mpi_get_nbits (pk.n)+7)/8;
 
-  return GPG_ERR_NO_ERROR;
+      rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen);
+      if (!rc)
+        {
+          rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                               "(enc-val(rsa(a%b)))",
+                                               (int)emlen, em));
+          gcry_free (em);
+        }
+    }
+  else
+    rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                         "(enc-val(rsa(a%m)))",
+                                         result));
+
+  mpi_free (result);
+  return rc;
 }
 
 
@@ -993,10 +1016,12 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
 
 
 static gcry_err_code_t
-rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
+rsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey,
           int flags, int hashalgo)
 {
+  gpg_err_code_t rc;
   RSA_secret_key sk;
+  gcry_mpi_t result;
 
   (void)algo;
   (void)flags;
@@ -1011,10 +1036,31 @@ rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
   sk.p = skey[3];
   sk.q = skey[4];
   sk.u = skey[5];
-  resarr[0] = mpi_alloc( mpi_get_nlimbs (sk.n));
-  secret (resarr[0], data, &sk);
+  result = mpi_alloc (mpi_get_nlimbs (sk.n));
+  secret (result, data, &sk);
+  if ((flags & PUBKEY_FLAG_FIXEDLEN))
+    {
+      /* We need to make sure to return the correct length to avoid
+         problems with missing leading zeroes.  */
+      unsigned char *em;
+      size_t emlen = (mpi_get_nbits (sk.n)+7)/8;
 
-  return GPG_ERR_NO_ERROR;
+      rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen);
+      if (!rc)
+        {
+          rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                               "(sig-val(rsa(s%b)))",
+                                               (int)emlen, em));
+          gcry_free (em);
+        }
+    }
+  else
+    rc = gcry_err_code (gcry_sexp_build (r_result, NULL,
+                                         "(sig-val(rsa(s%M)))",
+                                         result));
+  mpi_free (result);
+
+  return rc;
 }
 
 
index 07e91c6..1d2c87e 100644 (file)
@@ -836,3 +836,61 @@ gcry_mpi_aprint (enum gcry_mpi_format format,
     *nwritten = n;
   return rc;
 }
+
+
+/* Turn VALUE into an octet string and store it in an allocated buffer
+   at R_FRAME or - if R_RAME is NULL - copy it into the caller
+   provided buffer SPACE; either SPACE or R_FRAME may be used.  If
+   SPACE if not NULL, the caller must provide a buffer of at least
+   NBYTES.  If the resulting octet string is shorter than NBYTES pad
+   it to the left with zeroes.  If VALUE does not fit into NBYTES
+   return an error code.  */
+gpg_err_code_t
+_gcry_mpi_to_octet_string (unsigned char **r_frame, void *space,
+                           gcry_mpi_t value, size_t nbytes)
+{
+  gpg_err_code_t rc;
+  size_t nframe, noff, n;
+  unsigned char *frame;
+
+  if (!r_frame == !space)
+    return GPG_ERR_INV_ARG;  /* Only one may be used.  */
+
+  if (r_frame)
+    *r_frame = NULL;
+
+  rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
+                                      NULL, 0, &nframe, value));
+  if (rc)
+    return rc;
+  if (nframe > nbytes)
+    return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES.  */
+
+  noff = (nframe < nbytes)? nbytes - nframe : 0;
+  n = nframe + noff;
+  if (space)
+    frame = space;
+  else
+    {
+      frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n);
+      if (!frame)
+        {
+          rc = gpg_err_code_from_syserror ();
+          return rc;
+        }
+    }
+  if (noff)
+    memset (frame, 0, noff);
+  nframe += noff;
+  rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG,
+                                      frame+noff, nframe-noff, NULL, value));
+  if (rc)
+    {
+      gcry_free (frame);
+      return rc;
+    }
+
+  if (r_frame)
+    *r_frame = frame;
+  return 0;
+}
index a641a07..121d9f5 100644 (file)
@@ -68,7 +68,7 @@ typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
 
 /* Type for the pk_encrypt function.  */
 typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo,
-                                             gcry_mpi_t *resarr,
+                                             gcry_sexp_t *r_result,
                                              gcry_mpi_t data,
                                              gcry_mpi_t *pkey,
                                              int flags);
@@ -82,7 +82,7 @@ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo,
 
 /* Type for the pk_sign function.  */
 typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo,
-                                          gcry_mpi_t *resarr,
+                                          gcry_sexp_t *r_result,
                                           gcry_mpi_t data,
                                           gcry_mpi_t *skey,
                                            int flags,
index 8d3afbf..dde24ce 100644 (file)
@@ -29,6 +29,7 @@
 #define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
 #define PUBKEY_FLAG_RFC6979        (1 << 1)
 #define PUBKEY_FLAG_EDDSA          (1 << 2)
+#define PUBKEY_FLAG_FIXEDLEN       (1 << 3)
 
 enum pk_operation
   {
index f24e968..3466951 100644 (file)
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -167,6 +167,9 @@ byte *_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
                                    unsigned *r_nbytes, int *sign);
 void  _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer,
                              unsigned int nbytes, int sign );
+gpg_err_code_t _gcry_mpi_to_octet_string (unsigned char **r_frame,
+                                          void *space,
+                                          gcry_mpi_t value, size_t nbytes);
 
 /*-- mpi-add.c --*/
 #define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
index e113913..baa6a7a 100644 (file)
@@ -326,7 +326,7 @@ one_test (int testno, const char *sk, const char *pk,
   if (s_tmp)
     {
       s_tmp2 = s_tmp;
-      s_tmp = gcry_sexp_find_token (s_tmp2, "ecdsa", 0);
+      s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0);
       if (s_tmp)
         {
           gcry_sexp_release (s_tmp2);