PK: use wrappers and function pointers for verify
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index 2f70085..f06ec68 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -24,6 +24,7 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+
 #ifndef POLARSSL_PK_H
 #define POLARSSL_PK_H
 
@@ -33,6 +34,10 @@
 #include "rsa.h"
 #endif
 
+#if defined(POLARSSL_ECP_C)
+#include "ecp.h"
+#endif
+
 #if defined(POLARSSL_ECDSA_C)
 #include "ecdsa.h"
 #endif
@@ -77,13 +82,28 @@
 } pk_type_t;
 
 /**
+ * \brief           Public key info
+ */
+typedef struct
+{
+    /** Public key type */
+    pk_type_t type;
+
+    /** Verify signature */
+    int (*verify_func)( void *ctx,
+                        const unsigned char *hash, const md_info_t *md_info,
+                        const unsigned char *sig, size_t sig_len );
+} pk_info_t;
+
+/**
  * \brief           Public key container
  */
 typedef struct
 {
-    pk_type_t   type;       /**< Public key type */
-    void *      data;       /**< Public key data */
-    int         dont_free;  /**< True if data must not be freed */
+    const pk_info_t *   info;       /**< Public key informations */
+    pk_type_t           type;       /**< Public key type (temporary) */
+    void *              data;       /**< Public key data */
+    int                 dont_free;  /**< True if data must not be freed */
 } pk_context;
 
 /**
@@ -157,4 +177,4 @@
 }
 #endif
 
-#endif /* pk.h */
+#endif /* POLARSSL_PK_H */
diff --git a/include/polarssl/pk_wrap.h b/include/polarssl/pk_wrap.h
new file mode 100644
index 0000000..7d2c3dd
--- /dev/null
+++ b/include/polarssl/pk_wrap.h
@@ -0,0 +1,47 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_PK_WRAP_H
+#define POLARSSL_PK_WRAP_H
+
+#include "config.h"
+
+#include "pk.h"
+
+#if defined(POLARSSL_RSA_C)
+extern const pk_info_t rsa_info;
+#endif
+
+#if defined(POLARSSL_ECP_C)
+extern const pk_info_t eckey_info;
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+extern const pk_info_t ecdsa_info;
+#endif
+
+#endif /* POLARSSL_PK_WRAP_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 3fa76a9..9eea7dc 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -40,6 +40,7 @@
      pkcs11.c
      pkcs12.c
      pk.c
+     pk_wrap.c
      rsa.c
      sha1.c
      sha256.c
diff --git a/library/Makefile b/library/Makefile
index 48c3bdc..044e2b7 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -49,7 +49,7 @@
 		oid.o									\
 		padlock.o	pbkdf2.o	pem.o			\
 		pkcs5.o		pkcs11.o	pkcs12.o		\
-		pk.o									\
+		pk.o		pk_wrap.o					\
 		rsa.o		sha1.o		sha256.o		\
 		sha512.o	ssl_cache.o	ssl_cli.o		\
 		ssl_srv.o   ssl_ciphersuites.o			\
diff --git a/library/pk.c b/library/pk.c
index c5583c3..1210490 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -26,6 +26,7 @@
 #include "polarssl/config.h"
 
 #include "polarssl/pk.h"
+#include "polarssl/pk_wrap.h"
 
 #if defined(POLARSSL_RSA_C)
 #include "polarssl/rsa.h"
@@ -54,6 +55,7 @@
     if( ctx == NULL )
         return;
 
+    ctx->info = NULL;
     ctx->type = POLARSSL_PK_NONE;
     ctx->data = NULL;
     ctx->dont_free = 0;
@@ -89,6 +91,7 @@
     if( ! ctx->dont_free )
         polarssl_free( ctx->data );
 
+    ctx->info = NULL;
     ctx->type = POLARSSL_PK_NONE;
     ctx->data = NULL;
 }
@@ -99,6 +102,7 @@
 int pk_set_type( pk_context *ctx, pk_type_t type )
 {
     size_t size;
+    const pk_info_t *info;
 
     if( ctx->type == type )
         return( 0 );
@@ -108,17 +112,26 @@
 
 #if defined(POLARSSL_RSA_C)
     if( type == POLARSSL_PK_RSA )
+    {
         size = sizeof( rsa_context );
+        info = &rsa_info;
+    }
     else
 #endif
 #if defined(POLARSSL_ECP_C)
     if( type == POLARSSL_PK_ECKEY || type == POLARSSL_PK_ECKEY_DH )
+    {
         size = sizeof( ecp_keypair );
+        info = &eckey_info;
+    }
     else
 #endif
 #if defined(POLARSSL_ECDSA_C)
     if( type == POLARSSL_PK_ECDSA )
+    {
         size = sizeof( ecdsa_context );
+        info = &ecdsa_info;
+    }
     else
 #endif
         return( POLARSSL_ERR_PK_TYPE_MISMATCH );
@@ -128,6 +141,7 @@
 
     memset( ctx->data, 0, size );
     ctx->type = type;
+    ctx->info = info;
 
     return( 0 );
 }
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
new file mode 100644
index 0000000..fe47b38
--- /dev/null
+++ b/library/pk_wrap.c
@@ -0,0 +1,106 @@
+/*
+ *  Public Key abstraction layer: wrapper functions
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#include "polarssl/pk_wrap.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+
+#if defined(POLARSSL_RSA_C)
+static int rsa_verify_wrap( void *ctx,
+                   const unsigned char *hash, const md_info_t *md_info,
+                   const unsigned char *sig, size_t sig_len )
+{
+    ((void) sig_len);
+
+    return( rsa_pkcs1_verify( (rsa_context *) ctx,
+                RSA_PUBLIC, md_info->type, 0, hash, sig ) );
+}
+
+const pk_info_t rsa_info = {
+    POLARSSL_PK_RSA,
+    rsa_verify_wrap,
+};
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECDSA_C)
+int ecdsa_verify_wrap( void *ctx,
+                       const unsigned char *hash, const md_info_t *md_info,
+                       const unsigned char *sig, size_t sig_len )
+{
+    return( ecdsa_read_signature( (ecdsa_context *) ctx,
+                hash, md_info->size, sig, sig_len ) );
+}
+
+const pk_info_t ecdsa_info = {
+    POLARSSL_PK_ECDSA,
+    ecdsa_verify_wrap,
+};
+#endif /* POLARSSL_ECDSA_C */
+
+#if defined(POLARSSL_ECP_C)
+static int eckey_verify_wrap( void *ctx,
+                       const unsigned char *hash, const md_info_t *md_info,
+                       const unsigned char *sig, size_t sig_len )
+{
+#if !defined(POLARSSL_ECDSA_C)
+    ((void) ctx);
+    ((void) hash);
+    ((void) md_info);
+    ((void) sig);
+    ((void) sig_len);
+
+    return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+#else
+    int ret;
+    ecdsa_context ecdsa;
+
+    ecdsa_init( &ecdsa );
+
+    ret = ecdsa_from_keypair( &ecdsa, ctx ) ||
+          ecdsa_verify_wrap( &ecdsa, hash, md_info, sig, sig_len );
+
+    ecdsa_free( &ecdsa );
+
+    return( ret );
+#endif /* POLARSSL_ECDSA_C */
+}
+
+const pk_info_t eckey_info = {
+    POLARSSL_PK_ECKEY,
+    eckey_verify_wrap,
+};
+#endif /* POLARSSL_ECP_C */
diff --git a/library/x509parse.c b/library/x509parse.c
index b686403..15823bd 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -3348,8 +3348,8 @@
         if( crl_list->sig_pk == POLARSSL_PK_RSA )
         {
             if( ca->pk.type != POLARSSL_PK_RSA ||
-                rsa_pkcs1_verify( pk_rsa( ca->pk ), RSA_PUBLIC,
-                        crl_list->sig_md, 0, hash, crl_list->sig.p ) != 0 )
+                ca->pk.info->verify_func( ca->pk.data,
+                    hash, md_info, crl_list->sig.p, crl_list->sig.len ) != 0 )
             {
                 flags |= BADCRL_NOT_TRUSTED;
                 break;
@@ -3361,10 +3361,8 @@
         if( crl_list->sig_pk == POLARSSL_PK_ECDSA )
         {
             if( ! pk_can_ecdsa( ca->pk ) ||
-                pk_ec_to_ecdsa( &ca->pk ) != 0 ||
-                ecdsa_read_signature( (ecdsa_context *) ca->pk.data,
-                        hash, md_info->size,
-                        crl_list->sig.p, crl_list->sig.len ) != 0 )
+                ca->pk.info->verify_func( ca->pk.data,
+                    hash, md_info, crl_list->sig.p, crl_list->sig.len ) != 0 )
             {
                 flags |= BADCRL_NOT_TRUSTED;
                 break;
@@ -3487,8 +3485,8 @@
         if( child->sig_pk == POLARSSL_PK_RSA )
         {
             if( trust_ca->pk.type != POLARSSL_PK_RSA ||
-                rsa_pkcs1_verify( pk_rsa( trust_ca->pk ), RSA_PUBLIC,
-                        child->sig_md, 0, hash, child->sig.p ) != 0 )
+                trust_ca->pk.info->verify_func( trust_ca->pk.data,
+                        hash, md_info, child->sig.p, child->sig.len ) != 0 )
             {
                 trust_ca = trust_ca->next;
                 continue;
@@ -3500,10 +3498,8 @@
         if( child->sig_pk == POLARSSL_PK_ECDSA )
         {
             if( ! pk_can_ecdsa( trust_ca->pk ) ||
-                pk_ec_to_ecdsa( &trust_ca->pk ) != 0 ||
-                ecdsa_read_signature( (ecdsa_context *) trust_ca->pk.data,
-                        hash, md_info->size,
-                        child->sig.p, child->sig.len ) != 0 )
+                trust_ca->pk.info->verify_func( trust_ca->pk.data,
+                        hash, md_info, child->sig.p, child->sig.len ) != 0 )
             {
                 trust_ca = trust_ca->next;
                 continue;
@@ -3586,8 +3582,8 @@
         if( child->sig_pk == POLARSSL_PK_RSA )
         {
             if( parent->pk.type != POLARSSL_PK_RSA ||
-                rsa_pkcs1_verify( pk_rsa( parent->pk ), RSA_PUBLIC,
-                        child->sig_md, 0, hash, child->sig.p ) != 0 )
+                parent->pk.info->verify_func( parent->pk.data,
+                        hash, md_info, child->sig.p, child->sig.len ) != 0 )
             {
                 *flags |= BADCERT_NOT_TRUSTED;
             }
@@ -3598,10 +3594,8 @@
         if( child->sig_pk == POLARSSL_PK_ECDSA )
         {
             if( ! pk_can_ecdsa( parent->pk ) ||
-                pk_ec_to_ecdsa( &parent->pk ) != 0 ||
-                ecdsa_read_signature( (ecdsa_context *) parent->pk.data,
-                        hash, md_info->size,
-                        child->sig.p, child->sig.len ) != 0 )
+                parent->pk.info->verify_func( parent->pk.data,
+                        hash, md_info, child->sig.p, child->sig.len ) != 0 )
             {
                 *flags |= BADCERT_NOT_TRUSTED;
             }