Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/dh.c
15010 views
1
//
2
// dh.c DH functions
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
SYMCRYPT_ERROR
11
SYMCRYPT_CALL
12
SymCryptDhSecretAgreement(
13
_In_ PCSYMCRYPT_DLKEY pkPrivate,
14
_In_ PCSYMCRYPT_DLKEY pkPublic,
15
SYMCRYPT_NUMBER_FORMAT format,
16
UINT32 flags,
17
_Out_writes_( cbAgreedSecret ) PBYTE pbAgreedSecret,
18
SIZE_T cbAgreedSecret )
19
{
20
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
21
22
PBYTE pbScratch = NULL;
23
SIZE_T cbScratch = 0;
24
PBYTE pbScratchInternal = NULL;
25
SIZE_T cbScratchInternal = 0;
26
27
PCSYMCRYPT_DLGROUP pDlgroup = NULL;
28
29
PSYMCRYPT_MODELEMENT peRes = NULL;
30
UINT32 cbModelement = 0;
31
32
UINT32 nBitsOfExp = 0;
33
34
// Make sure that the keys may be used in DH
35
if ( ((pkPrivate->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DH) == 0) ||
36
((pkPublic->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DH) == 0) )
37
{
38
scError = SYMCRYPT_INVALID_ARGUMENT;
39
goto cleanup;
40
}
41
42
// Make sure we only specify the correct flags and that
43
// there is a private key
44
if ( (flags != 0) || (!pkPrivate->fHasPrivateKey) )
45
{
46
scError = SYMCRYPT_INVALID_ARGUMENT;
47
goto cleanup;
48
}
49
50
// Check that the group is the same for both keys
51
if ( SymCryptDlgroupIsSame( pkPrivate->pDlgroup, pkPublic->pDlgroup ) )
52
{
53
pDlgroup = pkPrivate->pDlgroup;
54
}
55
else
56
{
57
scError = SYMCRYPT_INVALID_ARGUMENT;
58
goto cleanup;
59
}
60
61
// Check the output buffer has the correct size
62
if (cbAgreedSecret != SymCryptDlkeySizeofPublicKey( pkPrivate ))
63
{
64
scError = SYMCRYPT_WRONG_BLOCK_SIZE;
65
goto cleanup;
66
}
67
68
// Objects and scratch space size calculation
69
cbModelement = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
70
cbScratch = cbModelement +
71
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pDlgroup->nDigitsOfP ),
72
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pDlgroup->nDigitsOfP ));
73
74
// Scratch space allocation
75
pbScratch = SymCryptCallbackAlloc( cbScratch );
76
if ( pbScratch == NULL )
77
{
78
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
79
goto cleanup;
80
}
81
82
// Creating temporary
83
pbScratchInternal = pbScratch;
84
cbScratchInternal = cbScratch;
85
peRes = SymCryptModElementCreate( pbScratchInternal, cbModelement, pDlgroup->pmP );
86
pbScratchInternal += cbModelement;
87
cbScratchInternal -= cbModelement;
88
89
SYMCRYPT_ASSERT( peRes != NULL);
90
91
// Fix the bits of the exponent (the private key might be either mod Q, mod 2^nBitsPriv, or mod P)
92
if (pkPrivate->fPrivateModQ)
93
{
94
nBitsOfExp = pkPrivate->nBitsPriv;
95
}
96
else
97
{
98
nBitsOfExp = pDlgroup->nBitsOfP;
99
}
100
101
// Calculate the secret
102
SymCryptModExp(
103
pDlgroup->pmP,
104
pkPublic->pePublicKey,
105
pkPrivate->piPrivateKey,
106
nBitsOfExp,
107
0, // SC safe
108
peRes,
109
pbScratchInternal,
110
cbScratchInternal );
111
112
// Check if the result is zero
113
if ( SymCryptModElementIsZero( pDlgroup->pmP, peRes ) )
114
{
115
scError = SYMCRYPT_INVALID_BLOB;
116
goto cleanup;
117
}
118
119
// Output the result
120
scError = SymCryptModElementGetValue(
121
pDlgroup->pmP,
122
peRes,
123
pbAgreedSecret,
124
cbAgreedSecret,
125
format,
126
pbScratchInternal,
127
cbScratchInternal );
128
if ( scError != SYMCRYPT_NO_ERROR )
129
{
130
goto cleanup;
131
}
132
133
cleanup:
134
if ( pbScratch != NULL )
135
{
136
SymCryptWipe( pbScratch, cbScratch );
137
SymCryptCallbackFree( pbScratch );
138
}
139
140
return scError;
141
}
142
143