Implement public key encryption in write_encrypted_pms.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 17 Jan 2017 13:18:14 +0000 (22:18 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 17 Jan 2017 13:18:14 +0000 (22:18 +0900)
* src/x509.c (ntbtls_x509_pk_encrypt): New.
* src/protocol-cli.c (write_encrypted_pms): Call
ntbtls_x509_pk_encrypt.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
src/ntbtls-int.h
src/protocol-cli.c
src/x509.c

index 3ee0fc5..eb5db10 100644 (file)
@@ -376,6 +376,10 @@ gpg_error_t _ntbtls_x509_verify (x509_cert_t cert, x509_cert_t trust_ca,
 
 int _ntbtls_x509_can_do (x509_privkey_t privkey, pk_algo_t pkalgo);
 
+gpg_error_t _ntbtls_x509_pk_encrypt (x509_cert_t cert,
+                                     const unsigned char *input, size_t ilen,
+                                     unsigned char *output, size_t *olen,
+                                     size_t osize);
 
 /*-- dhm.c --*/
 gpg_error_t _ntbtls_dhm_new (dhm_context_t *r_dhm);
index 80f7082..7740a5f 100644 (file)
@@ -1214,11 +1214,10 @@ write_encrypted_pms (ntbtls_t tls,
   /*     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); */
   /*   } */
 
-  /* err = pk_encrypt (&tls->session_negotiate->peer_chain->pk, */
-  /*                   p, tls->handshake->pmslen, */
-  /*                   tls->out_msg + offset + len_bytes, olen, */
-  /*                   TLS_MAX_CONTENT_LEN - offset - len_bytes); */
-  err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+  err = _ntbtls_x509_pk_encrypt (tls->session_negotiate->peer_chain,
+                                 p, tls->handshake->pmslen,
+                                 tls->out_msg + offset + len_bytes, olen,
+                                 TLS_MAX_CONTENT_LEN - offset - len_bytes);
   if (err)
     {
       debug_ret (1, "rsa_pkcs1_encrypt", err);
index 8c497f9..1439a3d 100644 (file)
@@ -209,3 +209,64 @@ _ntbtls_x509_can_do (x509_privkey_t privkey, pk_algo_t pk_alg)
   /* FIXME: Check that PRIVKEY matches PKALGO.  */
   return 1;
 }
+
+gpg_error_t
+_ntbtls_x509_pk_encrypt (x509_cert_t cert,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen, size_t osize)
+{
+  gpg_error_t err;
+  ksba_sexp_t buf;
+  size_t len;
+  gcry_sexp_t s_ciph, s_data, s_pkey;
+  const char *data;
+
+  buf = ksba_cert_get_public_key (cert->crt);
+  if (!buf)
+    return gpg_error (GPG_ERR_NO_PUBKEY);
+
+  len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
+  if (!len)
+    return gpg_error (GPG_ERR_BUG);
+
+  err = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len);
+  free (buf);
+  buf = NULL;
+  if (err)
+    return err;
+
+  err = gcry_sexp_build (&s_data, NULL, "(data (flags pkcs1) (value %b))",
+                         (int)ilen, input);
+  if (err)
+    {
+      gcry_sexp_release (s_pkey);
+      return err;
+    }
+
+  err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+  gcry_sexp_release (s_pkey);
+  gcry_sexp_release (s_data);
+  if (err)
+    return err;
+
+  s_data = gcry_sexp_find_token (s_ciph, "a", 0);
+  data = gcry_sexp_nth_data (s_data, 1, &len);
+  if (data == NULL)
+    {
+      gcry_sexp_release (s_data);
+      gcry_sexp_release (s_ciph);
+      return gpg_error (GPG_ERR_BAD_MPI);
+    }
+
+  if (osize < len)
+    {
+      gcry_sexp_release (s_data);
+      gcry_sexp_release (s_ciph);
+      return gpg_error (GPG_ERR_TOO_SHORT);
+    }
+  *olen = len;
+  memcpy (output, data, len);
+  gcry_sexp_release (s_data);
+  gcry_sexp_release (s_ciph);
+  return 0;
+}