Hans Leidekker : bcrypt: Add support for exporting legacy DSA public keys.
Alexandre Julliard
julliard at winehq.org
Tue Oct 6 15:33:11 CDT 2020
Module: wine
Branch: master
Commit: 2a91b0bead7e5c6d08e3a6b79a6feda242e66652
URL: https://source.winehq.org/git/wine.git/?a=commit;h=2a91b0bead7e5c6d08e3a6b79a6feda242e66652
Author: Hans Leidekker <hans at codeweavers.com>
Date: Tue Oct 6 12:27:13 2020 +0200
bcrypt: Add support for exporting legacy DSA public keys.
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/bcrypt/bcrypt_internal.h | 4 ++
dlls/bcrypt/bcrypt_main.c | 2 +-
dlls/bcrypt/gnutls.c | 93 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index 5edc9e6c9c..13d6ba8d6c 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -27,6 +27,7 @@
#include "wincrypt.h"
#include "bcrypt.h"
+#define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
#define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
typedef struct
@@ -164,9 +165,12 @@ struct key_symmetric
ULONG secret_len;
};
+#define KEY_FLAG_LEGACY_DSA_V2 0x00000001
+
struct key_asymmetric
{
ULONG bitlen; /* ignored for ECC keys */
+ ULONG flags;
UCHAR *pubkey;
ULONG pubkey_len;
DSSSEED dss_seed;
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 7f8b08869d..bc6ec69918 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -991,7 +991,7 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
return STATUS_SUCCESS;
}
else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ) ||
- !wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ))
+ !wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB ))
{
*size = key->u.a.pubkey_len;
if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index ed632dfd4c..2d80b74aac 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -804,6 +804,89 @@ static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bit
return STATUS_SUCCESS;
}
+static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, const DSSSEED *seed, ULONG bitlen,
+ UCHAR **pubkey, ULONG *pubkey_len )
+{
+ BLOBHEADER *hdr;
+ DSSPUBKEY *dsskey;
+ gnutls_datum_t p, q, g, y;
+ UCHAR *dst, *src;
+ int i, ret, size = sizeof(*hdr) + sizeof(*dsskey) + sizeof(*seed);
+
+ if (bitlen > 1024)
+ {
+ FIXME( "bitlen > 1024 not supported\n" );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (!(hdr = RtlAllocateHeap( GetProcessHeap(), 0, size + p.size + q.size + g.size + y.size )))
+ {
+ pgnutls_perror( ret );
+ free( p.data ); free( q.data ); free( g.data ); free( y.data );
+ return STATUS_NO_MEMORY;
+ }
+
+ hdr->bType = PUBLICKEYBLOB;
+ hdr->bVersion = 2;
+ hdr->reserved = 0;
+ hdr->aiKeyAlg = CALG_DSS_SIGN;
+
+ dsskey = (DSSPUBKEY *)(hdr + 1);
+ dsskey->magic = MAGIC_DSS1;
+ dsskey->bitlen = bitlen;
+
+ dst = (UCHAR *)(dsskey + 1);
+ if (p.size % 2)
+ {
+ src = p.data + 1;
+ p.size--;
+ }
+ else src = p.data;
+ for (i = 0; i < p.size; i++) dst[i] = src[p.size - i - 1];
+
+ dst += p.size;
+ if (q.size % 2)
+ {
+ src = q.data + 1;
+ q.size--;
+ }
+ else src = q.data;
+ for (i = 0; i < q.size; i++) dst[i] = src[q.size - i - 1];
+
+ dst += q.size;
+ if (g.size % 2)
+ {
+ src = g.data + 1;
+ g.size--;
+ }
+ else src = g.data;
+ for (i = 0; i < g.size; i++) dst[i] = src[g.size - i - 1];
+
+ dst += g.size;
+ if (y.size % 2)
+ {
+ src = y.data + 1;
+ y.size--;
+ }
+ else src = y.data;
+ for (i = 0; i < y.size; i++) dst[i] = src[y.size - i - 1];
+
+ dst += y.size;
+ memcpy( dst, seed, sizeof(*seed) );
+
+ *pubkey = (UCHAR *)hdr;
+ *pubkey_len = size + p.size + q.size + g.size + y.size;
+
+ free( p.data ); free( q.data ); free( g.data ); free( y.data );
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS CDECL key_asymmetric_generate( struct key *key )
{
gnutls_pk_algorithm_t pk_alg;
@@ -1069,6 +1152,7 @@ static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG le
unsigned char dummy[128];
unsigned char *data, p_data[128], q_data[20], g_data[128], x_data[20];
int i, ret, size;
+ NTSTATUS status;
if ((ret = pgnutls_privkey_init( &handle )))
{
@@ -1118,9 +1202,18 @@ static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG le
return STATUS_INTERNAL_ERROR;
}
+ if ((status = export_gnutls_pubkey_dsa_capi( handle, &key->u.a.dss_seed, key->u.a.bitlen, &key->u.a.pubkey,
+ &key->u.a.pubkey_len )))
+ {
+ pgnutls_privkey_deinit( handle );
+ return status;
+ }
+
memcpy( &key->u.a.dss_seed, data, sizeof(key->u.a.dss_seed) );
+ key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
key_data(key)->privkey = handle;
+
return STATUS_SUCCESS;
}
More information about the wine-cvs
mailing list