SSL async callback: cert is not always from mbedtls_ssl_conf_own_cert

The certificate passed to async callbacks may not be the one set by
mbedtls_ssl_conf_own_cert. For example, when using an SNI callback,
it's whatever the callback is using. Document this, and add a test
case (and code sample) with SNI.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 097b86a..b199e2e 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -601,9 +601,12 @@
  * \param ssl             The SSL connection instance. It should not be
  *                        modified other than via mbedtls_ssl_async_set_data().
  * \param cert            Certificate containing the public key.
- *                        This is one of the pointers passed to
+ *                        In simple cases, this is one of the pointers passed to
  *                        mbedtls_ssl_conf_own_cert() when configuring the SSL
- *                        connection.
+ *                        connection. However, if other callbacks are used, this
+ *                        property may not hold. For example, if an SNI callback
+ *                        is registered with mbedtls_ssl_conf_sni(), then
+ *                        this callback determines what certificate is used.
  * \param md_alg          Hash algorithm.
  * \param hash            Buffer containing the hash. This buffer is
  *                        no longer valid when the function returns.
@@ -665,9 +668,12 @@
  * \param ssl             The SSL connection instance. It should not be
  *                        modified other than via mbedtls_ssl_async_set_data().
  * \param cert            Certificate containing the public key.
- *                        This is one of the pointers passed to
+ *                        In simple cases, this is one of the pointers passed to
  *                        mbedtls_ssl_conf_own_cert() when configuring the SSL
- *                        connection.
+ *                        connection. However, if other callbacks are used, this
+ *                        property may not hold. For example, if an SNI callback
+ *                        is registered with mbedtls_ssl_conf_sni(), then
+ *                        this callback determines what certificate is used.
  * \param input           Buffer containing the input ciphertext. This buffer
  *                        is no longer valid when the function returns.
  * \param input_len       Size of the \p input buffer in bytes.
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 838f41d..b1f2382 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -204,7 +204,7 @@
 #define USAGE_SSL_ASYNC \
     "    async_operations=%%c...   d=decrypt, s=sign (default: -=off)\n" \
     "    async_private_delay1=%%d  Asynchronous delay for key_file or preloaded key\n" \
-    "    async_private_delay2=%%d  Asynchronous delay for key_file2\n" \
+    "    async_private_delay2=%%d  Asynchronous delay for key_file2 and sni\n" \
     "                              default: -1 (not asynchronous)\n" \
     "    async_private_error=%%d   Async callback error injection (default=0=none,\n" \
     "                              1=start, 2=cancel, 3=resume, negative=first time only)"
@@ -897,7 +897,7 @@
 
 typedef struct
 {
-    ssl_async_key_slot_t slots[2];
+    ssl_async_key_slot_t slots[3]; /* key, key2, sni */
     size_t slots_used;
     ssl_async_inject_error_t inject_error;
     int (*f_rng)(void *, unsigned char *, size_t);
@@ -965,7 +965,9 @@
 
     for( slot = 0; slot < config_data->slots_used; slot++ )
     {
-        if( config_data->slots[slot].cert == cert )
+        if( memcmp( &config_data->slots[slot].cert->pk,
+                    &cert->pk,
+                    sizeof( cert->pk ) ) == 0 )
             break;
     }
     if( slot == config_data->slots_used )
@@ -2376,7 +2378,24 @@
 
 #if defined(SNI_OPTION)
     if( opt.sni != NULL )
+    {
         mbedtls_ssl_conf_sni( &conf, sni_callback, sni_info );
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        if( opt.async_private_delay2 >= 0 )
+        {
+            ret = ssl_async_set_key( &ssl_async_keys,
+                                     sni_info->cert, sni_info->key,
+                                     opt.async_private_delay2 );
+            if( ret < 0 )
+            {
+                mbedtls_printf( "  Test error: ssl_async_set_key failed (%d)\n",
+                                ret );
+                goto exit;
+            }
+            sni_info->key = NULL;
+        }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+    }
 #endif
 
 #if defined(MBEDTLS_ECP_C)
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 597a5f1..6afca2d 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -4113,6 +4113,20 @@
             -s "Async resume (slot [0-9]): sign done, status=0"
 
 requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
+run_test    "SSL async private: sign, SNI" \
+            "$P_SRV debug_level=3 \
+             async_operations=s async_private_delay1=0 async_private_delay2=0 \
+             crt_file=data_files/server5.crt key_file=data_files/server5.key \
+             sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
+            "$P_CLI server_name=polarssl.example" \
+            0 \
+            -s "Async sign callback: using key slot " \
+            -s "Async resume (slot [0-9]): sign done, status=0" \
+            -s "parse ServerName extension" \
+            -c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \
+            -c "subject name *: C=NL, O=PolarSSL, CN=polarssl.example"
+
+requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
 run_test    "SSL async private: decrypt, delay=0" \
             "$P_SRV \
              async_operations=d async_private_delay1=0 async_private_delay2=0" \