implemented gcrypt RSA encrypt/decrypt operations
authorMartin Willi <martin@strongswan.org>
Mon, 15 Jun 2009 16:07:57 +0000 (18:07 +0200)
committerMartin Willi <martin@strongswan.org>
Mon, 15 Jun 2009 16:07:57 +0000 (18:07 +0200)
src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c

index b9b7d8b..14a1470 100644 (file)
@@ -214,10 +214,47 @@ static bool sign(private_gcrypt_rsa_private_key_t *this, signature_scheme_t sche
  * Implementation of gcrypt_rsa_private_key.destroy.
  */
 static bool decrypt(private_gcrypt_rsa_private_key_t *this,
-                                       chunk_t crypto, chunk_t *plain)
+                                       chunk_t encrypted, chunk_t *plain)
 {
-       DBG1("RSA private key decryption not implemented");
-       return FALSE;
+       gcry_error_t err;
+       gcry_sexp_t in, out;
+       chunk_t padded;
+       u_char *pos = NULL;;
+       
+       err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))",
+                                                 encrypted.len, encrypted.ptr);
+       if (err)
+       {
+               DBG1("building decryption S-expression failed: %s", gpg_strerror(err));
+               return FALSE;
+       }
+       err = gcry_pk_decrypt(&out, in, this->key);
+       gcry_sexp_release(in);
+       if (err)
+       {
+               DBG1("decrypting pkcs1 data failed: %s", gpg_strerror(err));
+               return FALSE;
+       }
+       padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
+       /* result is padded, but gcrypt strips leading zero:
+        *  00 | 02 | RANDOM | 00 | DATA */
+       if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02)
+       {
+               pos = memchr(padded.ptr, 0x00, padded.len - 1);
+               if (pos)
+               {
+                       pos++;
+                       *plain = chunk_clone(chunk_create(
+                                                                               pos, padded.len - (pos - padded.ptr)));
+               }
+       }
+       gcry_sexp_release(out);
+       if (!pos)
+       {
+               DBG1("decrypted data has invalid pkcs1 padding");
+               return FALSE;
+       }
+       return TRUE;
 }
 
 /**
index 42c478c..909c43c 100644 (file)
@@ -202,13 +202,33 @@ static bool verify(private_gcrypt_rsa_public_key_t *this,
 }
 
 /**
- * Implementation of public_key_t.get_keysize.
+ * Implementation of public_key_t.encrypt.
  */
-static bool encrypt_(private_gcrypt_rsa_public_key_t *this, chunk_t crypto,
-                                       chunk_t *plain)
+static bool encrypt_(private_gcrypt_rsa_public_key_t *this, chunk_t plain,
+                                        chunk_t *encrypted)
 {
-       DBG1("RSA public key encryption not implemented");
-       return FALSE;
+       gcry_sexp_t in, out;
+       gcry_error_t err;
+       
+       /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
+        * 00 | 02 | RANDOM | 00 | DATA */
+       err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))",
+                                                 plain.len, plain.ptr);
+       if (err)
+       {
+               DBG1("building encryption S-expression failed: %s", gpg_strerror(err));
+               return FALSE;
+       }
+       err = gcry_pk_encrypt(&out, in, this->key);
+       gcry_sexp_release(in);
+       if (err)
+       {
+               DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err));
+               return FALSE;
+       }
+       *encrypted = gcrypt_rsa_find_token(out, "a");
+       gcry_sexp_release(out);
+       return !!encrypted->len;
 }
 
 /**