Browse code

--management-external-key for PolarSSL

Add --management-external-key support, compatible with the OpenSSL
implementation. Needs the flexibility of ssl_set_own_cert_alt(), which
is new in PolarSSL-1.2.

Signed-off-by: Joachim Schipper <joachim.schipper@fox-it.com>
Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <1379587649-25506-3-git-send-email-steffan.karger@fox-it.com>
URL: http://article.gmane.org/gmane.network.openvpn.devel/7886
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Joachim Schipper authored on 2013/09/19 19:47:28
Showing 3 changed files
... ...
@@ -121,6 +121,10 @@ tls_ctx_free(struct tls_root_ctx *ctx)
121 121
 	  free(ctx->priv_key_pkcs11);
122 122
       }
123 123
 #endif
124
+#if defined(MANAGMENT_EXTERNAL_KEY)
125
+      if (ctx->external_key != NULL)
126
+          free(ctx->external_key);
127
+#endif
124 128
 
125 129
       if (ctx->allowed_ciphers)
126 130
 	free(ctx->allowed_ciphers);
... ...
@@ -309,14 +313,95 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file,
309 309
 
310 310
 #ifdef MANAGMENT_EXTERNAL_KEY
311 311
 
312
+
313
+struct external_context {
314
+  size_t signature_length;
315
+};
316
+
317
+int
312 318
 tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,
313
-    const char *cert_file, const char *cert_file_inline
314
-    )
319
+    const char *cert_file, const char *cert_file_inline)
315 320
 {
316
-  msg(M_FATAL, "Use of management external keys not yet supported for PolarSSL.");
317
-  return false;
321
+  ASSERT(NULL != ctx);
322
+
323
+  tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline);
324
+
325
+  if (ctx->crt_chain == NULL)
326
+    return 0;
327
+
328
+  /* Most of the initialization happens in key_state_ssl_init() */
329
+  ALLOC_OBJ_CLEAR (ctx->external_key, struct external_context);
330
+  ctx->external_key->signature_length = ctx->crt_chain->rsa.len;
331
+
332
+  return 1;
318 333
 }
319 334
 
335
+static inline int external_pkcs1_sign( void *ctx_voidptr,
336
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode,
337
+    int hash_id, unsigned int hashlen, const unsigned char *hash,
338
+    unsigned char *sig )
339
+{
340
+  struct external_context * const ctx = ctx_voidptr;
341
+  char *in_b64 = NULL;
342
+  char *out_b64 = NULL;
343
+  int rv;
344
+
345
+  ASSERT(NULL != ctx);
346
+
347
+  if (RSA_PRIVATE != mode)
348
+    {
349
+      rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA;
350
+      goto done;
351
+    }
352
+
353
+  /*
354
+   * Normally (i.e. rsa_pkcs1_sign()), the padding is set in the context, and
355
+   * we have padding-specific code to handle various hash_id's here. Since the
356
+   * management client will RSA-sign the bytes we present without further
357
+   * processing, we only support SIG_RSA_RAW (PolarSSL's equivalent of
358
+   * OpenSSL's NID_md5_sha1).
359
+   */
360
+  ASSERT(hash_id == SIG_RSA_RAW);
361
+  /* convert 'from' to base64 */
362
+  if (openvpn_base64_encode (hash, hashlen, &in_b64) <= 0)
363
+    {
364
+      rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA;
365
+      goto done;
366
+    }
367
+
368
+  /* call MI for signature */
369
+  if (management)
370
+    out_b64 = management_query_rsa_sig (management, in_b64);
371
+  if (!out_b64)
372
+    {
373
+      rv = POLARSSL_ERR_RSA_PRIVATE_FAILED;
374
+      goto done;
375
+    }
376
+
377
+  /* decode base64 signature to binary and verify length */
378
+  if ( openvpn_base64_decode (out_b64, sig, ctx->signature_length) !=
379
+       ctx->signature_length )
380
+    {
381
+      rv = POLARSSL_ERR_RSA_PRIVATE_FAILED;
382
+      goto done;
383
+    }
384
+
385
+  rv = 0;
386
+
387
+ done:
388
+  if (in_b64)
389
+    free (in_b64);
390
+  if (out_b64)
391
+    free (out_b64);
392
+  return rv;
393
+}
394
+
395
+static inline size_t external_key_len(void *vctx)
396
+{
397
+  struct external_context * const ctx = vctx;
398
+
399
+  return ctx->signature_length;
400
+}
320 401
 #endif
321 402
 
322 403
 void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
... ...
@@ -530,6 +615,13 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
530 530
 	    ssl_pkcs11_key_len );
531 531
       else
532 532
 #endif
533
+#if defined(MANAGMENT_EXTERNAL_KEY)
534
+      if (ssl_ctx->external_key != NULL)
535
+        ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain,
536
+	   ssl_ctx->external_key, NULL, external_pkcs1_sign,
537
+	   external_key_len );
538
+      else
539
+#endif
533 540
 	ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key );
534 541
 
535 542
       /* Initialise SSL verification */
... ...
@@ -30,6 +30,8 @@
30 30
 #ifndef SSL_POLARSSL_H_
31 31
 #define SSL_POLARSSL_H_
32 32
 
33
+#include "syshead.h"
34
+
33 35
 #include <polarssl/ssl.h>
34 36
 
35 37
 #if defined(ENABLE_PKCS11)
... ...
@@ -68,6 +70,9 @@ struct tls_root_ctx {
68 68
 #if defined(ENABLE_PKCS11)
69 69
     pkcs11_context *priv_key_pkcs11;	/**< PKCS11 private key */
70 70
 #endif
71
+#ifdef MANAGMENT_EXTERNAL_KEY
72
+    struct external_context *external_key; /**< Management external key */
73
+#endif
71 74
     int * allowed_ciphers;	/**< List of allowed ciphers for this connection */
72 75
 };
73 76
 
... ...
@@ -539,7 +539,7 @@ socket_defined (const socket_descriptor_t sd)
539 539
 /*
540 540
  * Enable external private key
541 541
  */
542
-#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL) && !defined(ENABLE_CRYPTO_POLARSSL)
542
+#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL)
543 543
 #define MANAGMENT_EXTERNAL_KEY
544 544
 #endif
545 545