This is not supported on native but it will be useful to implement public key import in dssenh.
Signed-off-by: Hans Leidekker hans@codeweavers.com --- 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 bc6ec69918..a91f31e9f0 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 2d80b74aac..94e375cc8c 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 );