From f79ca651aeff14a7f4e3443410a89441569ea080 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 6 Oct 2020 12:27:14 +0200 Subject: [PATCH] bcrypt: Add support for importing legacy DSA public keys. This is not supported on native but it will be useful to implement public key import in dssenh. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/bcrypt/bcrypt_main.c | 28 +++++++++++++++++++++++++ dlls/bcrypt/gnutls.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index bc6ec699184..a91f31e9f09 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1329,6 +1329,34 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP *ret_key = key; return STATUS_SUCCESS; } + else if (!wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB )) /* not supported on native */ + { + BLOBHEADER *hdr = (BLOBHEADER *)input; + DSSPUBKEY *pubkey; + ULONG size; + + if (alg->id != ALG_ID_DSA) return STATUS_NOT_SUPPORTED; + if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER; + + if (hdr->bType != PUBLICKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN) + { + FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg ); + return STATUS_NOT_SUPPORTED; + } + + if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER; + pubkey = (DSSPUBKEY *)(hdr + 1); + if (pubkey->magic != MAGIC_DSS1) return STATUS_NOT_SUPPORTED; + + size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); + if (input_len < size) return STATUS_INVALID_PARAMETER; + + if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, (BYTE *)hdr, size ))) return status; + key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2; + + *ret_key = key; + return STATUS_SUCCESS; + } FIXME( "unsupported key type %s\n", debugstr_w(type) ); return STATUS_NOT_SUPPORTED; diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 2d80b74aac4..94e375cc8cf 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -1336,6 +1336,54 @@ static NTSTATUS import_gnutls_pubkey_dsa( struct key *key, gnutls_pubkey_t *gnut return STATUS_SUCCESS; } +static NTSTATUS import_gnutls_pubkey_dsa_capi( struct key *key, gnutls_pubkey_t *gnutls_key ) +{ + BLOBHEADER *hdr; + DSSPUBKEY *pubkey; + gnutls_datum_t p, q, g, y; + unsigned char *data, p_data[128], q_data[20], g_data[128], y_data[128]; + int i, ret, size; + + if ((ret = pgnutls_pubkey_init( gnutls_key ))) + { + pgnutls_perror( ret ); + return STATUS_INTERNAL_ERROR; + } + + hdr = (BLOBHEADER *)key->u.a.pubkey; + pubkey = (DSSPUBKEY *)(hdr + 1); + size = pubkey->bitlen / 8; + data = (unsigned char *)(pubkey + 1); + + p.data = p_data; + p.size = size; + for (i = 0; i < p.size; i++) p.data[i] = data[p.size - i - 1]; + data += p.size; + + q.data = q_data; + q.size = sizeof(q_data); + for (i = 0; i < q.size; i++) q.data[i] = data[q.size - i - 1]; + data += q.size; + + g.data = g_data; + g.size = size; + for (i = 0; i < g.size; i++) g.data[i] = data[g.size - i - 1]; + data += g.size; + + y.data = y_data; + y.size = sizeof(y_data); + for (i = 0; i < y.size; i++) y.data[i] = data[y.size - i - 1]; + + if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y ))) + { + pgnutls_perror( ret ); + pgnutls_pubkey_deinit( *gnutls_key ); + return STATUS_INTERNAL_ERROR; + } + + return STATUS_SUCCESS; +} + static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_key ) { switch (key->alg_id) @@ -1349,7 +1397,10 @@ static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_k return import_gnutls_pubkey_rsa( key, gnutls_key ); case ALG_ID_DSA: - return import_gnutls_pubkey_dsa( key, gnutls_key ); + if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2) + return import_gnutls_pubkey_dsa_capi( key, gnutls_key ); + else + return import_gnutls_pubkey_dsa( key, gnutls_key ); default: FIXME("algorithm %u not yet supported\n", key->alg_id ); -- 2.11.4.GIT