<p>There's an MSDN article <a href="http://msdn.microsoft.com/en-us/library/aa919730.aspx" rel="nofollow noreferrer">here</a>, but I'm not getting very far:</p>

<pre><code>p = 139;
g = 5;

CRYPT_DATA_BLOB pblob;
pblob.cbData = sizeof( ULONG );
pblob.pbData = ( LPBYTE ) &amp;p;

CRYPT_DATA_BLOB gblob;
gblob.cbData = sizeof( ULONG );
gblob.pbData = ( LPBYTE ) &amp;g;

HCRYPTKEY hKey;
if ( ::CryptGenKey( m_hCryptoProvider, CALG_DH_SF,
                    CRYPT_PREGEN, &amp;hKey ) )
{
    ::CryptSetKeyParam( hKey, KP_P, ( LPBYTE ) &amp;pblob, 0 );
</code></pre>

<p>Fails here with <code>NTE_BAD_DATA</code>.  I'm using <code>MS_DEF_DSS_DH_PROV</code>.   What gives?</p>

It looks to me that
```
KP_P
```
,
```
KP_G
```
,
```
KP_Q
```
are for DSS keys (Digital Signature Standard?). For Diffie-Hellman it looks like you're supposed to use
```
KP_PUB_PARAMS
```
and pass a
```
DATA_BLOB
```
that points to a
```
DHPUBKEY_VER3
```
structure.
Note that the article you're pointing to is from the Windows Mobile/Windows CE SDK. It wouldn't be the first time that CE worked differently from the desktop/server.
EDIT: CE does not implement
```
KP_PUB_PARAMS
```
. To use this structure on the desktop, see
Diffie-Hellman Version 3 Public Key BLOBs
.