mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
Enable signing via provider for management-external-key
- Add a function to set as sign_op during key import. The
function passes the signature request to management interface,
and returns the result to the provider.
v2 changes: Method to do digest added to match the changes in
the provider signature callback.
TODO:
- Allow passing the undigested message to management interface
- Add pkcs1 DigestInfo header when required
Signed-off-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <20211214165928.30676-8-selva.nair@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg23428.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
57abdcfc38
commit
199df03bf5
3 changed files with 113 additions and 6 deletions
|
|
@ -1169,7 +1169,7 @@ end:
|
|||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
#if defined(ENABLE_MANAGEMENT) && !defined(HAVE_XKEY_PROVIDER)
|
||||
|
||||
/* encrypt */
|
||||
static int
|
||||
|
|
@ -1470,7 +1470,9 @@ err:
|
|||
return 0;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER > 1.1.0 dev && !defined(OPENSSL_NO_EC) */
|
||||
#endif /* ENABLE_MANAGEMENT && !HAVE_XKEY_PROVIDER */
|
||||
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
int
|
||||
tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,10 +67,13 @@ typedef struct {
|
|||
*
|
||||
* @returns 1 on success, 0 on error.
|
||||
*
|
||||
* The data in tbs is just the digest with no DigestInfo header added. This is
|
||||
* If sigalg.op = "Sign", the data in tbs is the digest. If sigalg.op = "DigestSign"
|
||||
* it is the message that the backend should hash wih appropriate hash algorithm before
|
||||
* signing. In the former case no DigestInfo header is added to tbs. This is
|
||||
* unlike the deprecated RSA_sign callback which provides encoded digest.
|
||||
* For RSA_PKCS1 signatures, the external signing function must encode the digest
|
||||
* before signing. The digest algorithm used is passed in the sigalg structure.
|
||||
* before signing. The digest algorithm used (or to be used) is passed in the sigalg
|
||||
* structure.
|
||||
*/
|
||||
typedef int (XKEY_EXTERNAL_SIGN_fn)(void *handle, unsigned char *sig, size_t *siglen,
|
||||
const unsigned char *tbs, size_t tbslen,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "error.h"
|
||||
#include "buffer.h"
|
||||
#include "xkey_common.h"
|
||||
#include "manage.h"
|
||||
#include "base64.h"
|
||||
|
||||
#ifdef HAVE_XKEY_PROVIDER
|
||||
|
||||
|
|
@ -48,6 +50,31 @@ static const char *const props = XKEY_PROV_PROPS;
|
|||
|
||||
XKEY_EXTERNAL_SIGN_fn xkey_management_sign;
|
||||
|
||||
/** helper to compute digest */
|
||||
static int
|
||||
xkey_digest(const unsigned char *src, size_t srclen, unsigned char *buf,
|
||||
size_t *buflen, const char *mdname)
|
||||
{
|
||||
dmsg(D_LOW, "In xkey_digest");
|
||||
EVP_MD *md = EVP_MD_fetch(NULL, mdname, NULL); /* from default context */
|
||||
if (!md)
|
||||
{
|
||||
msg(M_WARN, "WARN: xkey_digest: MD_fetch failed for <%s>", mdname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int len = (unsigned int) *buflen;
|
||||
if (EVP_Digest(src, srclen, buf, &len, md, NULL) != 1)
|
||||
{
|
||||
msg(M_WARN, "WARN: xkey_digest: EVP_Digest failed");
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_free(md);
|
||||
|
||||
*buflen = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load external key for signing via management interface.
|
||||
* The public key must be passed in by the caller as we may not
|
||||
|
|
@ -94,13 +121,88 @@ xkey_load_management_key(OSSL_LIB_CTX *libctx, EVP_PKEY *pubkey)
|
|||
return pkey;
|
||||
}
|
||||
|
||||
/* not yet implemented */
|
||||
/**
|
||||
* Signature callback for xkey_provider with management-external-key
|
||||
*
|
||||
* @param handle Unused -- may be null
|
||||
* @param sig On successful return signature is in sig.
|
||||
* @param siglen On entry *siglen has length of buffer sig,
|
||||
* on successful return size of signature
|
||||
* @param tbs hash or message to be signed
|
||||
* @param tbslen len of data in dgst
|
||||
* @param sigalg extra signature parameters
|
||||
*
|
||||
* @return signature length or -1 on error.
|
||||
*/
|
||||
int
|
||||
xkey_management_sign(void *unused, unsigned char *sig, size_t *siglen,
|
||||
const unsigned char *tbs, size_t tbslen, XKEY_SIGALG alg)
|
||||
{
|
||||
msg(M_FATAL, "FATAL ERROR: A sign callback for this key is not implemented.");
|
||||
return 0;
|
||||
(void) unused;
|
||||
char alg_str[128];
|
||||
unsigned char buf[EVP_MAX_MD_SIZE]; /* for computing digest if required */
|
||||
size_t buflen = sizeof(buf);
|
||||
|
||||
if (!strcmp(alg.op, "DigestSign"))
|
||||
{
|
||||
dmsg(D_LOW, "xkey_management_sign: computing digest");
|
||||
if (xkey_digest(tbs, tbslen, buf, &buflen, alg.mdname))
|
||||
{
|
||||
tbs = buf;
|
||||
tbslen = buflen;
|
||||
alg.op = "Sign";
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(alg.keytype, "EC"))
|
||||
{
|
||||
strncpynt(alg_str, "ECDSA", sizeof(alg_str));
|
||||
}
|
||||
/* else assume RSA key */
|
||||
else if (!strcmp(alg.padmode, "pkcs1"))
|
||||
{
|
||||
strncpynt(alg_str, "RSA_PKCS1_PADDING", sizeof(alg_str));
|
||||
}
|
||||
else if (!strcmp(alg.padmode, "none"))
|
||||
{
|
||||
strncpynt(alg_str, "RSA_NO_PADDING", sizeof(alg_str));
|
||||
}
|
||||
else if (!strcmp(alg.padmode, "pss"))
|
||||
{
|
||||
openvpn_snprintf(alg_str, sizeof(alg_str), "%s,hashalg=%s,saltlen=%s",
|
||||
"RSA_PKCS1_PSS_PADDING", alg.mdname,alg.saltlen);
|
||||
}
|
||||
else {
|
||||
msg(M_NONFATAL, "Unsupported RSA padding mode in signature request<%s>",
|
||||
alg.padmode);
|
||||
return 0;
|
||||
}
|
||||
dmsg(D_LOW, "xkey management_sign: requesting sig with algorithm <%s>", alg_str);
|
||||
|
||||
char *in_b64 = NULL;
|
||||
char *out_b64 = NULL;
|
||||
int len = -1;
|
||||
|
||||
int bencret = openvpn_base64_encode(tbs, (int) tbslen, &in_b64);
|
||||
|
||||
if (management && bencret > 0)
|
||||
{
|
||||
out_b64 = management_query_pk_sig(management, in_b64, alg_str);
|
||||
}
|
||||
if (out_b64)
|
||||
{
|
||||
len = openvpn_base64_decode(out_b64, sig, (int) *siglen);
|
||||
}
|
||||
free(in_b64);
|
||||
free(out_b64);
|
||||
|
||||
*siglen = (len > 0) ? len : 0;
|
||||
|
||||
return (*siglen > 0);
|
||||
}
|
||||
|
||||
#endif /* HAVE_XKEY_PROVIDER */
|
||||
|
|
|
|||
Loading…
Reference in a new issue