Browse code

mbedtls: make external signing code generic

This prepares for reusing this code from the mbedtls pkcs11 implementation.
The change itself should not have any functional impact.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <1536916459-25900-2-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17465.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Steffan Karger authored on 2018/09/14 18:14:18
Showing 2 changed files
... ...
@@ -173,12 +173,6 @@ tls_ctx_free(struct tls_root_ctx *ctx)
173 173
             free(ctx->priv_key_pkcs11);
174 174
         }
175 175
 #endif
176
-#if defined(MANAGMENT_EXTERNAL_KEY)
177
-        if (ctx->external_key != NULL)
178
-        {
179
-            free(ctx->external_key);
180
-        }
181
-#endif
182 176
 
183 177
         if (ctx->allowed_ciphers)
184 178
         {
... ...
@@ -462,13 +456,6 @@ tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
462 462
     return 0;
463 463
 }
464 464
 
465
-#ifdef MANAGMENT_EXTERNAL_KEY
466
-
467
-
468
-struct external_context {
469
-    size_t signature_length;
470
-};
471
-
472 465
 /**
473 466
  * external_pkcs1_sign implements a mbed TLS rsa_sign_func callback, that uses
474 467
  * the management interface to request an RSA signature for the supplied hash.
... ...
@@ -495,11 +482,9 @@ external_pkcs1_sign( void *ctx_voidptr,
495 495
                      unsigned char *sig )
496 496
 {
497 497
     struct external_context *const ctx = ctx_voidptr;
498
-    char *in_b64 = NULL;
499
-    char *out_b64 = NULL;
500 498
     int rv;
501
-    unsigned char *p = sig;
502
-    size_t asn_len = 0, oid_size = 0, sig_len = 0;
499
+    uint8_t *to_sign = NULL;
500
+    size_t asn_len = 0, oid_size = 0;
503 501
     const char *oid = NULL;
504 502
 
505 503
     if (NULL == ctx)
... ...
@@ -535,12 +520,14 @@ external_pkcs1_sign( void *ctx_voidptr,
535 535
         asn_len = 10 + oid_size;
536 536
     }
537 537
 
538
-    sig_len = ctx->signature_length;
539
-    if ( (SIZE_MAX - hashlen) < asn_len || (hashlen + asn_len) > sig_len)
538
+    if ((SIZE_MAX - hashlen) < asn_len
539
+        || ctx->signature_length < (asn_len + hashlen))
540 540
     {
541 541
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
542 542
     }
543 543
 
544
+    ALLOC_ARRAY_CLEAR(to_sign, uint8_t, asn_len + hashlen);
545
+    uint8_t *p = to_sign;
544 546
     if (md_alg != MBEDTLS_MD_NONE)
545 547
     {
546 548
         /*
... ...
@@ -565,34 +552,16 @@ external_pkcs1_sign( void *ctx_voidptr,
565 565
         *p++ = MBEDTLS_ASN1_OCTET_STRING;
566 566
         *p++ = hashlen;
567 567
 
568
-        /* Determine added ASN length */
569
-        asn_len = p - sig;
568
+        /* Double-check ASN length */
569
+        ASSERT(asn_len == p - to_sign);
570 570
     }
571 571
 
572 572
     /* Copy the hash to be signed */
573
-    memcpy( p, hash, hashlen );
574
-
575
-    /* convert 'from' to base64 */
576
-    if (openvpn_base64_encode(sig, asn_len + hashlen, &in_b64) <= 0)
577
-    {
578
-        rv = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
579
-        goto done;
580
-    }
573
+    memcpy(p, hash, hashlen);
581 574
 
582
-    /* call MI for signature */
583
-    if (management)
584
-    {
585
-        out_b64 = management_query_pk_sig(management, in_b64);
586
-    }
587
-    if (!out_b64)
588
-    {
589
-        rv = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
590
-        goto done;
591
-    }
592
-
593
-    /* decode base64 signature to binary and verify length */
594
-    if (openvpn_base64_decode(out_b64, sig, ctx->signature_length) !=
595
-        ctx->signature_length)
575
+    /* Call external signature function */
576
+    if (!ctx->sign(ctx->sign_ctx, to_sign, asn_len + hashlen, sig,
577
+                   ctx->signature_length))
596 578
     {
597 579
         rv = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
598 580
         goto done;
... ...
@@ -601,14 +570,7 @@ external_pkcs1_sign( void *ctx_voidptr,
601 601
     rv = 0;
602 602
 
603 603
 done:
604
-    if (in_b64)
605
-    {
606
-        free(in_b64);
607
-    }
608
-    if (out_b64)
609
-    {
610
-        free(out_b64);
611
-    }
604
+    free(to_sign);
612 605
     return rv;
613 606
 }
614 607
 
... ...
@@ -621,7 +583,8 @@ external_key_len(void *vctx)
621 621
 }
622 622
 
623 623
 int
624
-tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
624
+tls_ctx_use_external_signing_func(struct tls_root_ctx *ctx,
625
+                                  external_sign_func sign_func, void *sign_ctx)
625 626
 {
626 627
     ASSERT(NULL != ctx);
627 628
 
... ...
@@ -631,11 +594,12 @@ tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
631 631
         return 1;
632 632
     }
633 633
 
634
-    ALLOC_OBJ_CLEAR(ctx->external_key, struct external_context);
635
-    ctx->external_key->signature_length = mbedtls_pk_get_len(&ctx->crt_chain->pk);
634
+    ctx->external_key.signature_length = mbedtls_pk_get_len(&ctx->crt_chain->pk);
635
+    ctx->external_key.sign = sign_func;
636
+    ctx->external_key.sign_ctx = sign_ctx;
636 637
 
637 638
     ALLOC_OBJ_CLEAR(ctx->priv_key, mbedtls_pk_context);
638
-    if (!mbed_ok(mbedtls_pk_setup_rsa_alt(ctx->priv_key, ctx->external_key,
639
+    if (!mbed_ok(mbedtls_pk_setup_rsa_alt(ctx->priv_key, &ctx->external_key,
639 640
                                           NULL, external_pkcs1_sign, external_key_len)))
640 641
     {
641 642
         return 1;
... ...
@@ -643,6 +607,47 @@ tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
643 643
 
644 644
     return 0;
645 645
 }
646
+
647
+#ifdef MANAGMENT_EXTERNAL_KEY
648
+
649
+/** Query the management interface for a signature, see external_sign_func. */
650
+static bool
651
+management_sign_func(void *sign_ctx, const void *src, size_t src_len,
652
+                     void *dst, size_t dst_len)
653
+{
654
+    bool ret = false;
655
+    char *src_b64 = NULL;
656
+    char *dst_b64 = NULL;
657
+
658
+    if (!management || (openvpn_base64_encode(src, src_len, &src_b64) <= 0))
659
+    {
660
+        goto cleanup;
661
+    }
662
+
663
+    if (!(dst_b64 = management_query_pk_sig(management, src_b64)))
664
+    {
665
+        goto cleanup;
666
+    }
667
+
668
+    if (openvpn_base64_decode(dst_b64, dst, dst_len) != dst_len)
669
+    {
670
+        goto cleanup;
671
+    }
672
+
673
+    ret = true;
674
+cleanup:
675
+    free (src_b64);
676
+    free (dst_b64);
677
+
678
+    return ret;
679
+}
680
+
681
+int
682
+tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
683
+{
684
+    return tls_ctx_use_external_signing_func(ctx, management_sign_func, NULL);
685
+}
686
+
646 687
 #endif /* ifdef MANAGMENT_EXTERNAL_KEY */
647 688
 
648 689
 void
... ...
@@ -58,6 +58,30 @@ typedef struct {
58 58
 } bio_ctx;
59 59
 
60 60
 /**
61
+ * External signing function prototype.  A function pointer to a function
62
+ * implementing this prototype is provided to
63
+ * tls_ctx_use_external_signing_func().
64
+ *
65
+ * @param sign_ctx  The context for the signing function.
66
+ * @param src       The data to be signed,
67
+ * @param src_len   The length of src, in bytes.
68
+ * @param dst       The destination buffer for the signature.
69
+ * @param dst_len   The length of the destination buffer.
70
+ *
71
+ * @return true if signing succeeded, false otherwise.
72
+ */
73
+typedef bool (*external_sign_func)(
74
+        void *sign_ctx, const void *src, size_t src_size,
75
+        void *dst, size_t dst_size);
76
+
77
+/** Context used by external_pkcs1_sign() */
78
+struct external_context {
79
+    size_t signature_length;
80
+    external_sign_func sign;
81
+    void *sign_ctx;
82
+};
83
+
84
+/**
61 85
  * Structure that wraps the TLS context. Contents differ depending on the
62 86
  * SSL library used.
63 87
  *
... ...
@@ -78,9 +102,7 @@ struct tls_root_ctx {
78 78
 #if defined(ENABLE_PKCS11)
79 79
     mbedtls_pkcs11_context *priv_key_pkcs11;    /**< PKCS11 private key */
80 80
 #endif
81
-#ifdef MANAGMENT_EXTERNAL_KEY
82
-    struct external_context *external_key; /**< Management external key */
83
-#endif
81
+    struct external_context external_key; /**< External key context */
84 82
     int *allowed_ciphers;       /**< List of allowed ciphers for this connection */
85 83
     mbedtls_x509_crt_profile cert_profile; /**< Allowed certificate types */
86 84
 };
... ...
@@ -91,5 +113,18 @@ struct key_state_ssl {
91 91
     bio_ctx bio_ctx;
92 92
 };
93 93
 
94
+/**
95
+ * Call the supplied signing function to create a TLS signature during the
96
+ * TLS handshake.
97
+ *
98
+ * @param ctx                   TLS context to use.
99
+ * @param sign_func             Signing function to call.
100
+ * @param sign_ctx              Context for the sign function.
101
+ *
102
+ * @return                      0 if successful, 1 if an error occurred.
103
+ */
104
+int tls_ctx_use_external_signing_func(struct tls_root_ctx *ctx,
105
+                                      external_sign_func sign_func,
106
+                                      void *sign_ctx);
94 107
 
95 108
 #endif /* SSL_MBEDTLS_H_ */