diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 33b04e4f2..5925a0419 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,14 @@
+Mon Jan 24 22:24:38 CET 2000  Werner Koch  <wk@gnupg.de>
+
+	* pubkey.c (gcry_pk_decrypt): Implemented.
+	(gcry_pk_encrypt): Implemented.
+	(gcry_pk_testkey): New.
+	(gcry_pk_genkey): New.
+	(pubkey_decrypt): Made static.
+	(pubkey_encrypt): Ditto.
+	(pubkey_check_secret_key): Ditto.
+	(pubkey_generate): Ditto.
+
 Mon Jan 24 13:04:28 CET 2000  Werner Koch  <wk@gnupg.de>
 
 	* pubkey.c (pubkey_nbits): Removed and replaced by ...
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 949e3b9ca..4def6f699 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -95,6 +95,7 @@ static struct {
 	{  NULL }};
 
 
+static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
 static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
 static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
 		      int (*cmp)(void *, MPI), void *opaque );
@@ -432,7 +433,7 @@ pubkey_get_nenc( int algo )
 }
 
 
-int
+static int
 pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
 {
     int i;
@@ -447,7 +448,7 @@ pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
 }
 
 
-int
+static int
 pubkey_check_secret_key( int algo, MPI *skey )
 {
     int i;
@@ -467,7 +468,7 @@ pubkey_check_secret_key( int algo, MPI *skey )
  * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
  * algorithm allows this - check with pubkey_get_nenc() )
  */
-int
+static int
 pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
 {
     int i, rc;
@@ -504,12 +505,12 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
  * result is a pointer to a mpi variable which will receive a
  * newly allocated mpi or NULL in case of an error.
  */
-int
+static int
 pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
 {
     int i, rc;
 
-    *result = NULL; /* so the caller can always do an mpi_free */
+    *result = NULL; /* so the caller can always do a mpi_free */
     if( DBG_CIPHER ) {
 	log_debug("pubkey_decrypt: algo=%d\n", algo );
 	for(i=0; i < pubkey_get_nskey(algo); i++ )
@@ -751,20 +752,196 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
 }
 
 
-
-
-
-int
-gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey )
+/****************
+ * Take sexp and return an array of MPI as used for our internal decrypt
+ * function.
+ */
+static int
+sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
 {
-	/* ... */
+    GCRY_SEXP list, l2;
+    const char *name;
+    const char *s;
+    size_t n;
+    int i, idx;
+    int algo;
+    const char *elems;
+    GCRY_MPI *array;
+
+    /* check that the first element is valid */
+    list = gcry_sexp_find_token( sexp, "enc-val" , 0 );
+    if( !list )
+	return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */
+    list = gcry_sexp_cdr( list );
+    if( !list )
+	return GCRYERR_NO_OBJ; /* no cdr for the data object */
+    name = gcry_sexp_car_data( list, &n );
+    if( !name )
+	return GCRYERR_INV_OBJ; /* invalid structure of object */
+    for(i=0; (s=enc_info_table[i].name); i++ ) {
+	if( strlen(s) == n && !memcmp( s, name, n ) )
+	    break;
+    }
+    if( !s )
+	return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
+    algo = enc_info_table[i].algo;
+    elems = enc_info_table[i].elements;
+    array = g10_calloc( (strlen(elems)+1) , sizeof *array );
+    if( !array )
+	return GCRYERR_NO_MEM;
+
+    idx = 0;
+    for(s=elems; *s; s++, idx++ ) {
+	l2 = gcry_sexp_find_token( list, s, 1 );
+	if( !l2 ) {
+	    g10_free( array );
+	    return GCRYERR_NO_OBJ; /* required parameter not found */
+	}
+	array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+	if( !array[idx] ) {
+	    g10_free( array );
+	    return GCRYERR_INV_OBJ; /* required parameter is invalid */
+	}
+    }
+
+    *retarray = array;
+    *retalgo = algo;
+
     return 0;
 }
 
+
+/****************
+ * Do a PK encrypt operation
+ *
+ * Caller has to provide a public key as the SEXP pkey and data as a SEXP
+ * with just one MPI in it.  The function returns a a sexp which may
+ * be passed tp to pk_decrypt.
+ * Later versions of this functions may take more complex input data.
+ *
+ * Returns: 0 or an errorcode.
+ *
+ * s_data = (<mpi>)
+ * s_pkey = <key-as-defined-in-sexp_to_key>
+ * r_ciph = (enc-val
+ *	      (<algo>
+ *		(<param_name1> <mpi>)
+ *		...
+ *		(<param_namen> <mpi>)
+ *	      ))
+ */
 int
-gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey )
+gcry_pk_encrypt( GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey )
 {
-	/* ... */
+    MPI *pkey, data, *ciph;
+    const char *algo_name, *algo_elems;
+    GCRY_SEXP *s_elems;
+    int i, rc, algo;
+
+    /* get the key */
+    rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
+    if( rc ) {
+	return rc;
+    }
+
+    /* get the name and the required size of the return value */
+    for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
+	if( enc_info_table[i].algo == algo )
+	    break;
+    }
+    if( !algo_name ) {
+	release_mpi_array( pkey );
+	return GCRYERR_INV_PK_ALGO;
+    }
+    algo_elems = enc_info_table[i].elements;
+
+    /* get the stuff we want to encrypt */
+    data = gcry_sexp_car_mpi( s_data, 0 );
+    if( !data ) {
+	release_mpi_array( pkey );
+	return GCRYERR_INV_OBJ;
+    }
+
+    /* Now we can encrypt data to ciph */
+    ciph = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph );
+    rc = pubkey_encrypt( algo, ciph, data, pkey );
+    release_mpi_array( pkey );
+    mpi_free( data );
+    if( rc ) {
+	g10_free( ciph );
+	return rc;
+    }
+
+    /* We did it.  Now build the return list */
+    s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
+    s_elems[0] = SEXP_NEW( algo_name, 0 );
+    for(i=0; algo_elems[i]; i++ ) {
+	char tmp[2];
+	tmp[0] = algo_elems[i];
+	tmp[1] = 0;
+	s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, ciph[i] );
+    }
+    release_mpi_array( ciph );
+    g10_free( ciph );
+
+    *r_ciph = SEXP_CONS( SEXP_NEW( "enc-val", 0 ),
+			 gcry_sexp_alist( s_elems ) );
+
+    g10_free( s_elems );
+    return 0;
+}
+
+/****************
+ * Do a PK decrypt operation
+ *
+ * Caller has to provide a secret key as the SEXP skey and data in a format
+ * as created by gcry_pk_encrypt.  Currently the function returns
+ * simply a MPI.  Later versions of this functions may return a more
+ * complex data structure.
+ *
+ * Returns: 0 or an errorcode.
+ *
+ * s_data = (enc-val
+ *	      (<algo>
+ *		(<param_name1> <mpi>)
+ *		...
+ *		(<param_namen> <mpi>)
+ *	      ))
+ * s_skey = <key-as-defined-in-sexp_to_key>
+ * r_plain= (<mpi>)   FIXME: Return a more structered value
+ */
+int
+gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
+{
+    MPI *skey, *data, plain;
+    int rc, algo, dataalgo;
+
+    rc = sexp_to_key( s_skey, 1, &skey, &algo );
+    if( rc ) {
+	return rc;
+    }
+    rc = sexp_to_enc( s_data, &data, &dataalgo );
+    if( rc ) {
+	release_mpi_array( skey );
+	return rc;
+    }
+    if( algo != dataalgo ) {
+	release_mpi_array( skey );
+	release_mpi_array( data );
+	return -1; /* fixme: add real errornumber - algo does not match */
+    }
+
+    rc = pubkey_decrypt( algo, &plain, data, skey );
+    if( rc ) {
+	release_mpi_array( skey );
+	release_mpi_array( data );
+	return -1; /* fixme: add real errornumber - decryption failed */
+    }
+
+    *r_plain = gcry_sexp_new_mpi( plain );
+    mpi_free( plain );
+    release_mpi_array( data );
+    release_mpi_array( skey );
     return 0;
 }
 
@@ -800,7 +977,7 @@ gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
     MPI *result;
     int i, algo, rc;
     const char *algo_name, *algo_elems;
-    GCRY_SEXP s;
+    GCRY_SEXP *s_elems;
 
     rc = sexp_to_key( s_skey, 1, &skey, &algo );
     if( rc )
@@ -832,16 +1009,21 @@ gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
 	return rc;
     }
 
-    s = SEXP_NEW( algo_name, 0 );
+    s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
+    s_elems[0] = SEXP_NEW( algo_name, 0 );
     for(i=0; algo_elems[i]; i++ ) {
 	char tmp[2];
 	tmp[0] = algo_elems[i];
 	tmp[1] = 0;
-	s = gcry_sexp_append( s, gcry_sexp_new_name_mpi( tmp, result[i] ) );
+	s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, result[i] );
     }
+    release_mpi_array( result );
     g10_free( result );
-    *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ), s );
-    gcry_sexp_dump( *r_sig );
+
+    *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ),
+			gcry_sexp_alist( s_elems ) );
+
+    g10_free( s_elems );
     return 0;
 }
 
@@ -889,6 +1071,52 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
 }
 
 
+/****************
+ * Test a key.	This may be used either for a public or a secret key
+ * to see whether internal structre is valid.
+ *
+ * Returns: 0 or an errorcode.
+ *
+ * s_key = <key-as-defined-in-sexp_to_key>
+ */
+int
+gcry_pk_testkey( GCRY_SEXP s_key )
+{
+    MPI *key;
+    int rc, algo;
+
+    /* Note we currently support only secret key checking */
+    rc = sexp_to_key( s_key, 1, &key, &algo );
+    if( rc ) {
+	return rc;
+    }
+
+    rc = pubkey_check_secret_key( algo, key );
+    release_mpi_array( key );
+    return rc;
+}
+
+
+/****************
+ * Create a public key pair and return it in r_key.
+ * How the key is created depends on s_parms:
+ * (GNU
+ *  (genkey
+ *   (algo
+ *     (parameter_name_1 ....)
+ *	....
+ *     (parameter_name_n ....)
+ * )))
+ * The key is returned in a format depending on the
+ * algorithm. Both, private and secret key are returned
+ * and optionally some additional informatin.
+ */
+int
+gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
+{
+    return GCRYERR_NOT_IMPL;
+}
+
 /****************
  * Get the number of nbits from the public key
  * Hmmm: Should we have really this function or is it
diff --git a/g10/ChangeLog b/g10/ChangeLog
index e73bae4c1..537b48ede 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,16 @@
+Mon Jan 24 22:24:38 CET 2000  Werner Koch  <wk@gnupg.de>
+
+	* misc.c (mpi_read_opaque): Fixed double counting.
+
+	* seckey-cert.c (do_check): Removed buffer and the unmotivated free
+	on it.
+
+	* pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
+	* seckey-cert.c (pk_check_secret_key): Likewise.
+	* encode.c (pk_encrypt): Likewise.
+
+	* parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
+
 Mon Jan 24 13:04:28 CET 2000  Werner Koch  <wk@gnupg.de>
 
 	* misc.c (mpi_print): Use gcry_mpi_aprint.
diff --git a/g10/encode.c b/g10/encode.c
index e4d701e30..736eba6f6 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -41,6 +41,52 @@
 static int encode_simple( const char *filename, int mode );
 static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
 
+/****************
+ * Emulate our old PK interface here - sometime in the future we might
+ * change the internal design to directly fit to libgcrypt.
+ */
+static int
+pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
+{
+    GCRY_SEXP s_ciph, s_data, s_pkey;
+    int rc;
+
+    /* make a sexp from pkey */
+    if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
+	s_pkey = SEXP_CONS( SEXP_NEW( "public-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "elg", 3 ),
+			  gcry_sexp_new_name_mpi( "p", pkey[0] ),
+			  gcry_sexp_new_name_mpi( "g", pkey[1] ),
+			  gcry_sexp_new_name_mpi( "y", pkey[2] ),
+			  NULL ));
+    }
+    else
+	return G10ERR_PUBKEY_ALGO;
+
+    /* put the data into a simple list */
+    s_data = gcry_sexp_new_mpi( data );
+
+    /* pass it to libgcrypt */
+    rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey );
+    gcry_sexp_release( s_data );
+    gcry_sexp_release( s_pkey );
+
+    if( rc )
+	;
+    else { /* add better error handling or make gnupg use S-Exp directly */
+	GCRY_SEXP list = gcry_sexp_find_token( s_ciph, "a" , 0 );
+	assert( list );
+	resarr[0] = gcry_sexp_cdr_mpi( list, 0 );
+	assert( resarr[0] );
+	list = gcry_sexp_find_token( s_ciph, "b" , 0 );
+	assert( list );
+	resarr[1] = gcry_sexp_cdr_mpi( list, 0 );
+	assert( resarr[1] );
+    }
+
+    gcry_sexp_release( s_ciph );
+    return rc;
+}
 
 
 /****************
@@ -464,7 +510,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
 	 * number of bits we have to use.  We then encode the session
 	 * key in some way and we get it back in the big intger value
 	 * FRAME.  Then we use FRAME, the public key PK->PKEY and the
-	 * algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
+	 * algorithm number PK->PUBKEY_ALGO and pass it to pk_encrypt
 	 * which returns the encrypted value in the array ENC->DATA.
 	 * This array has a size which depends on the used algorithm
 	 * (e.g. 2 for ElGamal).  We don't need frame anymore because we
@@ -473,7 +519,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
 	 */
 	frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
 							  pk->pkey ) );
-	rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
+	rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
 	mpi_release( frame );
 	if( rc )
 	    log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
diff --git a/g10/g10.c b/g10/g10.c
index 192ac4ae4..b619a2dcc 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -488,7 +488,7 @@ make_username( const char *string )
 static void
 register_extension( const char *mainpgm, const char *fname )
 {
-  #warning fixme add resgitser cipher extension
+  #warning fixme add register cipher extension
   #if 0
     if( *fname != '/' ) { /* do tilde expansion etc */
 	char *tmp;
diff --git a/g10/keygen.c b/g10/keygen.c
index 805160696..70590bc89 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -204,9 +204,10 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     MPI *factors;
 
     assert( is_ELGAMAL(algo) );
-    rc = pubkey_generate( algo, nbits, skey, &factors );
+    /*rc = pubkey_generate( algo, nbits, skey, &factors );*/
+    rc = gcry_pk_genkey( NULL, NULL );
     if( rc ) {
-	log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
+	log_error("pk_genkey failed: %s\n", g10_errstr(rc) );
 	return rc;
     }
 
@@ -281,7 +282,8 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     if( nbits > 1024 )
 	nbits = 1024;
 
-    rc = pubkey_generate( GCRY_PK_DSA, nbits, skey, &factors );
+    /*rc = pubkey_generate( GCRY_PK_DSA, nbits, skey, &factors );*/
+    rc = gcry_pk_genkey( NULL, NULL );
     if( rc ) {
 	log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
 	return rc;
diff --git a/g10/misc.c b/g10/misc.c
index 1c311a6c0..d3c01f4ef 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -178,7 +178,7 @@ mpi_read(IOBUF inp, unsigned int *ret_nread, int secure)
 
 /****************
  * Same as mpi_read but the value is stored as an opaque MPI.
- * This function is used to read encrpted MPI of v3 packets.
+ * This function is used to read encrypted MPI of v3 packets.
  */
 GCRY_MPI
 mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
@@ -205,7 +205,6 @@ mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
     p = buf;
     for( i=0 ; i < nbytes; i++ ) {
 	p[i] = iobuf_get(inp) & 0xff;
-	nread++;
     }
     nread += nbytes;
     a = gcry_mpi_set_opaque(NULL, buf, nbits );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index dffb874b0..71fa19ed5 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1420,10 +1420,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
 		printf("\tencrypted stuff follows\n");
 	    }
 	}
-	else { /* v3 method: the mpi length is not encrypted */
+	else { /* unencrypted v4 or v3 method (where length is not encrypted) */
 	    for(i=npkey; i < nskey; i++ ) {
 		n = pktlen;
-		sk->skey[i] = mpi_read_opaque(inp, &n );
+		sk->skey[i] = sk->is_protected ? mpi_read_opaque(inp, &n )
+					       : mpi_read( inp, &n, 1 );
 		pktlen -=n;
 		if( list_mode ) {
 		    printf(  "\tskey[%d]: ", i);
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 925b5a4d0..70e4bc6c1 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -37,6 +37,74 @@
 static int get_it( PKT_pubkey_enc *k,
 		   DEK *dek, PKT_secret_key *sk, u32 *keyid );
 
+
+/****************
+ * Emulate our old PK interface here - sometime in the future we might
+ * change the internal design to directly fit to libgcrypt.
+ */
+static int
+pk_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
+{
+    GCRY_SEXP s_skey, s_data, s_plain;
+    int rc;
+
+    *result = NULL;
+    /* make a sexp from skey */
+    if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
+	s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "elg", 0 ),
+			  gcry_sexp_new_name_mpi( "p", skey[0] ),
+			  gcry_sexp_new_name_mpi( "g", skey[1] ),
+			  gcry_sexp_new_name_mpi( "y", skey[2] ),
+			  gcry_sexp_new_name_mpi( "x", skey[3] ),
+			  NULL ));
+    }
+    else if( algo == GCRY_PK_RSA ) {
+	s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "rsa", 0 ),
+			  gcry_sexp_new_name_mpi( "n", skey[0] ),
+			  gcry_sexp_new_name_mpi( "e", skey[1] ),
+			  gcry_sexp_new_name_mpi( "d", skey[2] ),
+			  gcry_sexp_new_name_mpi( "p", skey[3] ),
+			  gcry_sexp_new_name_mpi( "q", skey[4] ),
+			  gcry_sexp_new_name_mpi( "u", skey[5] ),
+			  NULL ));
+    }
+    else
+	return G10ERR_PUBKEY_ALGO;
+
+    /* put data into a S-Exp s_data */
+    if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
+	s_data = SEXP_CONS( SEXP_NEW( "enc-val", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "elg", 0 ),
+			  gcry_sexp_new_name_mpi( "a", data[0] ),
+			  gcry_sexp_new_name_mpi( "b", data[1] ),
+			  NULL ));
+    }
+    else if( algo == GCRY_PK_RSA ) {
+	s_data = SEXP_CONS( SEXP_NEW( "enc-val", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "rsa", 0 ),
+			  gcry_sexp_new_name_mpi( "a", data[0] ),
+			  NULL ));
+    }
+    else
+	BUG();
+
+    rc = gcry_pk_decrypt( &s_plain, s_data, s_skey );
+    gcry_sexp_release( s_skey );
+    gcry_sexp_release( s_data);
+    if( rc )
+	return rc;
+
+    *result = gcry_sexp_car_mpi( s_plain, 0 );
+    if( !*result )
+	return -1; /* oops */
+
+    return 0;
+}
+
+
+
 /****************
  * Get the session key from a pubkey enc paket and return
  * it in DEK, which should have been allocated in secure memory.
@@ -106,7 +174,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
     size_t nframe;
     u16 csum, csum2;
 
-    rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
+    rc = pk_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
     if( rc )
 	goto leave;
     if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &frame, &nframe, plain_dek ) )
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 10f7092d2..88ec69389 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -33,11 +33,58 @@
 #include "i18n.h"
 #include "status.h"
 
+/****************
+ * Emulate our old PK interface here - sometime in the future we might
+ * change the internal design to directly fit to libgcrypt.
+ */
+static int
+pk_check_secret_key( int algo, MPI *skey )
+{
+    GCRY_SEXP s_skey;
+    int rc;
+
+    /* make a sexp from skey */
+    if( algo == GCRY_PK_DSA ) {
+	s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "dsa", 0 ),
+			  gcry_sexp_new_name_mpi( "p", skey[0] ),
+			  gcry_sexp_new_name_mpi( "q", skey[1] ),
+			  gcry_sexp_new_name_mpi( "g", skey[2] ),
+			  gcry_sexp_new_name_mpi( "y", skey[3] ),
+			  gcry_sexp_new_name_mpi( "x", skey[4] ),
+			  NULL ));
+    }
+    else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
+	s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "elg", 0 ),
+			  gcry_sexp_new_name_mpi( "p", skey[0] ),
+			  gcry_sexp_new_name_mpi( "g", skey[1] ),
+			  gcry_sexp_new_name_mpi( "y", skey[2] ),
+			  gcry_sexp_new_name_mpi( "x", skey[3] ),
+			  NULL ));
+    }
+    else if( algo == GCRY_PK_RSA ) {
+	s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
+			  gcry_sexp_vlist( SEXP_NEW( "rsa", 0 ),
+			  gcry_sexp_new_name_mpi( "n", skey[0] ),
+			  gcry_sexp_new_name_mpi( "e", skey[1] ),
+			  gcry_sexp_new_name_mpi( "d", skey[2] ),
+			  gcry_sexp_new_name_mpi( "p", skey[3] ),
+			  gcry_sexp_new_name_mpi( "q", skey[4] ),
+			  gcry_sexp_new_name_mpi( "u", skey[5] ),
+			  NULL ));
+    }
+    else
+	return G10ERR_PUBKEY_ALGO;
+
+    rc = gcry_pk_testkey( s_skey );
+    gcry_sexp_release( s_skey );
+    return rc;
+}
 
 static int
 do_check( PKT_secret_key *sk )
 {
-    byte *buffer;
     u16 csum=0;
     int i, res;
     unsigned nbytes;
@@ -141,7 +188,7 @@ do_check( PKT_secret_key *sk )
 		    log_bug("gcry_mpi_scan failed in do_check: rc=%d\n", res);
 
 		csum += checksum_mpi( sk->skey[i] );
-		gcry_free( buffer );
+		gcry_free( data );
 	    }
 	}
 	gcry_cipher_close( cipher_hd );
@@ -152,7 +199,7 @@ do_check( PKT_secret_key *sk )
 	    return G10ERR_BAD_PASS;
 	}
 	/* the checksum may fail, so we also check the key itself */
-	res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
+	res = pk_check_secret_key( sk->pubkey_algo, sk->skey );
 	if( res ) {
 	    copy_secret_key( sk, save_sk );
 	    free_secret_key( save_sk );
@@ -165,6 +212,7 @@ do_check( PKT_secret_key *sk )
 	csum = 0;
 	for(i=pubkey_get_npkey(sk->pubkey_algo);
 		i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
+	    assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
 	    csum += checksum_mpi( sk->skey[i] );
 	}
 	if( csum != sk->csum )
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index 2d2ec8bdb..9465aa513 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -1,3 +1,7 @@
+Mon Jan 24 22:24:38 CET 2000  Werner Koch  <wk@gnupg.de>
+
+	* mpicoder.c (gcry_mpi_aprint): Now really returns the length.
+
 Mon Jan 24 13:04:28 CET 2000  Werner Koch  <wk@gnupg.de>
 
 	* mpiutil.c: Removed all memory debugging code.
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index ca805f28b..bd79aca5d 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -608,6 +608,8 @@ gcry_mpi_aprint( enum gcry_mpi_format format, void **buffer, size_t *nbytes,
 	g10_free(*buffer);
 	*buffer = NULL;
     }
+    else if( nbytes )
+	*nbytes = n;
     return rc;
 }