Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
06e125ab
Commit
06e125ab
authored
May 11, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
May 16, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rsaenh: Allow importing bigger RC2 keys.
Signed-off-by:
Paul Gofman
<
pgofman@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
0ce78430
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
260 additions
and
1 deletion
+260
-1
rsaenh.c
dlls/rsaenh/rsaenh.c
+42
-1
rsaenh.c
dlls/rsaenh/tests/rsaenh.c
+218
-0
No files found.
dlls/rsaenh/rsaenh.c
View file @
06e125ab
...
...
@@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
...
...
@@ -2627,6 +2628,23 @@ BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
return
FALSE
;
}
if
(
pCryptKey
->
aiAlgid
==
CALG_RC2
)
{
const
PROV_ENUMALGS_EX
*
info
;
if
(
!
(
info
=
get_algid_info
(
hProv
,
pCryptKey
->
aiAlgid
)))
{
FIXME
(
"Can't get algid info.
\n
"
);
SetLastError
(
NTE_BAD_KEY
);
return
FALSE
;
}
if
(
pCryptKey
->
dwKeyLen
>
info
->
dwMaxLen
/
8
)
{
SetLastError
(
NTE_BAD_KEY
);
return
FALSE
;
}
}
if
(
pCryptKey
->
dwState
==
RSAENH_KEYSTATE_IDLE
)
pCryptKey
->
dwState
=
RSAENH_KEYSTATE_ENCRYPTING
;
...
...
@@ -3318,7 +3336,30 @@ static BOOL import_symmetric_key(HCRYPTPROV hProv, const BYTE *pbData, DWORD dwD
return
FALSE
;
}
*
phKey
=
new_key
(
hProv
,
pBlobHeader
->
aiKeyAlg
,
dwKeyLen
<<
19
,
&
pCryptKey
);
if
(
pBlobHeader
->
aiKeyAlg
==
CALG_RC2
)
{
const
PROV_ENUMALGS_EX
*
info
;
info
=
get_algid_info
(
hProv
,
CALG_RC2
);
assert
(
info
);
if
(
!
dwKeyLen
)
dwKeyLen
=
info
->
dwDefaultLen
;
if
(
dwKeyLen
<
info
->
dwMinLen
/
8
||
dwKeyLen
>
128
)
{
WARN
(
"Invalid RC2 key, len %ld.
\n
"
,
dwKeyLen
);
*
phKey
=
(
HCRYPTKEY
)
INVALID_HANDLE_VALUE
;
SetLastError
(
NTE_BAD_DATA
);
}
else
if
((
*
phKey
=
alloc_key
(
hProv
,
pBlobHeader
->
aiKeyAlg
,
0
,
dwKeyLen
<<
3
,
&
pCryptKey
))
!=
(
HCRYPTKEY
)
INVALID_HANDLE_VALUE
&&
info
->
dwDefaultLen
==
40
&&
dwKeyLen
>
info
->
dwMaxLen
/
8
)
{
pCryptKey
->
dwEffectiveKeyLen
=
40
;
}
}
else
{
*
phKey
=
new_key
(
hProv
,
pBlobHeader
->
aiKeyAlg
,
dwKeyLen
<<
19
,
&
pCryptKey
);
}
if
(
*
phKey
==
(
HCRYPTKEY
)
INVALID_HANDLE_VALUE
)
{
free
(
pbDecrypted
);
...
...
dlls/rsaenh/tests/rsaenh.c
View file @
06e125ab
...
...
@@ -3985,6 +3985,221 @@ err:
}
}
static
void
test_rc2_import
(
void
)
{
static
const
DWORD
test_lengths
[]
=
{
128
+
8
,
256
,
512
,
1024
};
static
const
DWORD
mac_results
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0xc13650cf
,
0xa3e93efb
},
{
0x6f7be248
,
0x444b38b2
},
{
0x2c3534d2
,
0x29fca10c
},
{
0x2c3534d2
,
0x29fca10c
},
};
static
const
DWORD
mac_baseprov_results
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0x7e94a244
,
0x12a9ae17
},
{
0x2aaa6719
,
0xa671d9a6
},
{
0x2e730ce2
,
0x9ebe6016
},
{
0x2e730ce2
,
0x9ebe6016
},
};
static
const
DWORD
mac_results_old
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0xebe2155a
,
0xab2f58b7
},
{
0x4394ccb2
,
0xbe5c629b
},
{
0xd7bc2195
,
0x63fb2785
},
{
0xd7bc2195
,
0x63fb2785
},
};
static
const
DWORD
mac_baseprov_results_old
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0xe2ed2dec
,
0x5ae837ed
},
{
0x12f4b193
,
0xe3f6afc1
},
{
0x04d7f905
,
0x686d357b
},
{
0x04d7f905
,
0x686d357b
},
};
static
const
DWORD
hmac_results
[
ARRAY_SIZE
(
test_lengths
)][
4
]
=
{
{
0x2f44586d
,
0x76d04c9f
,
0xdae8fc03
,
0x27e870bd
},
{
0xbcde3186
,
0xd9892cd5
,
0x578c89f5
,
0xc2cba8e5
},
{
0xad2bf1cc
,
0xae4e2c1f
,
0xd1599a67
,
0x0167d802
},
{
0x6ee75968
,
0x52a0eff5
,
0x75340d85
,
0x87b64962
},
};
static
const
DWORD
decrypt_baseprov_results
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0x48c4ff05
,
0x9d880b90
},
{
0xcfee0629
,
0xfeab04a1
},
{
0x23c9336c
,
0x7f67b26e
},
{
0x23c9336c
,
0x7f67b26e
},
};
static
const
DWORD
decrypt_results
[
ARRAY_SIZE
(
test_lengths
)][
2
]
=
{
{
0xb37e1be2
,
0x1ed67048
},
{
0x7c7d0b04
,
0x3a74bb76
},
{
0x7bfd232c
,
0x93d52c4f
},
{
0x7bfd232c
,
0x93d52c4f
},
};
struct
key_blob
{
BLOBHEADER
h
;
union
{
DWORD
key_size
;
DWORD
alg_id
;
}
param
;
BYTE
data
[
512
];
}
key_data
;
const
DWORD
*
results
,
*
broken_results
;
HCRYPTKEY
exchange_key
,
key
;
DWORD
len
,
value
,
expected
;
DWORD
test_length
;
BYTE
data
[
2048
];
HCRYPTPROV
prov
;
HCRYPTHASH
hash
;
unsigned
int
i
;
HMAC_INFO
hmac
;
BOOL
ret
;
ret
=
CryptAcquireContextA
(
&
prov
,
NULL
,
NULL
,
PROV_RSA_AES
,
CRYPT_VERIFYCONTEXT
|
CRYPT_NEWKEYSET
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
/* CryptGenKey() favours advertised key length limit. */
ret
=
CryptGenKey
(
prov
,
CALG_RC2
,
128
<<
16
,
&
key
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
CryptDestroyKey
(
key
);
ret
=
CryptGenKey
(
prov
,
CALG_RC2
,
(
128
+
8
)
<<
16
,
&
key
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
CryptReleaseContext
(
prov
,
0
);
ret
=
CryptGetUserKey
(
hProv
,
AT_KEYEXCHANGE
,
&
exchange_key
);
ok
(
ret
,
"CryptGetUserKey failed.
\n
"
);
memset
(
&
key_data
.
h
,
0
,
sizeof
(
key_data
.
h
));
key_data
.
h
.
bVersion
=
CUR_BLOB_VERSION
;
key_data
.
h
.
aiKeyAlg
=
CALG_RC2
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
test_lengths
);
++
i
)
{
memset
(
key_data
.
data
,
0xcc
,
sizeof
(
key_data
.
data
));
test_length
=
test_lengths
[
i
];
winetest_push_context
(
"length %lu"
,
test_length
);
len
=
min
(
test_length
/
8
,
64
);
ret
=
CryptEncrypt
(
exchange_key
,
0
,
TRUE
,
0
,
key_data
.
data
,
&
len
,
sizeof
(
key_data
)
-
12
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
memset
(
key_data
.
data
+
len
,
0xee
,
sizeof
(
key_data
.
data
)
-
len
);
/* Importing a larger key as plaintext fails. */
key_data
.
h
.
bType
=
PLAINTEXTKEYBLOB
;
key_data
.
param
.
key_size
=
test_length
/
8
;
ret
=
CryptImportKey
(
hProv
,
(
BYTE
*
)
&
key_data
,
offsetof
(
struct
key_blob
,
data
[
test_length
/
8
]),
0
,
0
,
&
key
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
/* Importing a larger key as SIMPLEBLOB succeeds. */
key_data
.
h
.
bType
=
SIMPLEBLOB
;
key_data
.
param
.
alg_id
=
CALG_RSA_KEYX
;
ret
=
CryptImportKey
(
hProv
,
(
BYTE
*
)
&
key_data
,
offsetof
(
struct
key_blob
,
data
[
len
]),
exchange_key
,
0
,
&
key
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
/* Effective key length is a public key decrypted length except for the base provider
* where it is default length. */
len
=
sizeof
(
value
);
value
=
0xdeadbeef
;
ret
=
CryptGetKeyParam
(
key
,
KP_EFFECTIVE_KEYLEN
,
(
BYTE
*
)
&
value
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
expected
=
BASE_PROV
?
40
:
test_length
;
expected
=
min
(
expected
,
512
);
ok
(
value
==
expected
,
"Unexpected value %lu, expected %lu.
\n
"
,
value
,
expected
);
expected
=
min
(
test_length
,
512
);
ret
=
CryptGetKeyParam
(
key
,
KP_KEYLEN
,
(
BYTE
*
)
&
value
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
value
==
expected
,
"Unexpected value %lu, expected %lu.
\n
"
,
value
,
expected
);
/* The resulting key is not good for encryption. */
memset
(
data
,
0xcc
,
8
);
len
=
8
;
ret
=
CryptEncrypt
(
key
,
0
,
FALSE
,
0
,
data
,
&
len
,
sizeof
(
data
));
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
NTE_BAD_KEY
,
"Unexpected error %#lx.
\n
"
,
GetLastError
());
len
=
8
;
ret
=
CryptEncrypt
(
key
,
0
,
TRUE
,
0
,
data
,
&
len
,
sizeof
(
data
));
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
NTE_BAD_KEY
,
"Unexpected error %#lx.
\n
"
,
GetLastError
());
/* But decryption works. */
len
=
8
;
ret
=
CryptDecrypt
(
key
,
0
,
FALSE
,
0
,
data
,
&
len
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
len
==
8
,
"Unexpected len %lu.
\n
"
,
len
);
results
=
BASE_PROV
?
decrypt_baseprov_results
[
i
]
:
decrypt_results
[
i
];
ok
(
!
memcmp
(
data
,
results
,
len
),
"Data does not match.
\n
"
);
ret
=
CryptCreateHash
(
hProv
,
CALG_MAC
,
key
,
0
,
&
hash
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
data
[
0
]
=
0
;
ret
=
CryptHashData
(
hash
,
data
,
1
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
len
=
sizeof
(
value
);
ret
=
CryptGetHashParam
(
hash
,
HP_HASHSIZE
,
(
BYTE
*
)
&
value
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
value
==
8
,
"Unexpected value %lu.
\n
"
,
value
);
len
=
32
;
memset
(
data
,
0xcc
,
8
);
ret
=
CryptGetHashParam
(
hash
,
HP_HASHVAL
,
data
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
len
==
8
,
"Unexpected len %lu.
\n
"
,
len
);
results
=
BASE_PROV
?
mac_baseprov_results
[
i
]
:
mac_results
[
i
];
broken_results
=
BASE_PROV
?
mac_baseprov_results_old
[
i
]
:
mac_results_old
[
i
];
/* Hash state is affected by key state before Win8. */
ok
(
!
memcmp
(
data
,
results
,
len
)
||
broken
(
!
memcmp
(
data
,
broken_results
,
len
)),
"Hash does not match.
\n
"
);
CryptDestroyHash
(
hash
);
ret
=
CryptCreateHash
(
hProv
,
CALG_HMAC
,
key
,
0
,
&
hash
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
memset
(
&
hmac
,
0
,
sizeof
(
hmac
));
hmac
.
HashAlgid
=
CALG_MD5
;
memset
(
data
,
0
,
sizeof
(
data
));
hmac
.
pbInnerString
=
data
;
hmac
.
cbInnerString
=
test_length
;
hmac
.
pbOuterString
=
data
;
hmac
.
cbOuterString
=
test_length
;
ret
=
CryptSetHashParam
(
hash
,
HP_HMAC_INFO
,
(
BYTE
*
)
&
hmac
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
data
[
0
]
=
0
;
ret
=
CryptHashData
(
hash
,
data
,
1
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
len
=
sizeof
(
value
);
ret
=
CryptGetHashParam
(
hash
,
HP_HASHSIZE
,
(
BYTE
*
)
&
value
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
value
==
16
,
"Unexpected value %lu.
\n
"
,
value
);
len
=
16
;
ret
=
CryptGetHashParam
(
hash
,
HP_HASHVAL
,
data
,
&
len
,
0
);
ok
(
ret
,
"Failed, error %#lx.
\n
"
,
GetLastError
());
ok
(
len
==
16
,
"Unexpected len %lu.
\n
"
,
len
);
ok
(
!
memcmp
(
data
,
hmac_results
[
i
],
len
),
"Hash does not match.
\n
"
);
CryptDestroyHash
(
hash
);
CryptDestroyKey
(
key
);
winetest_pop_context
();
}
CryptDestroyKey
(
exchange_key
);
}
START_TEST
(
rsaenh
)
{
for
(
iProv
=
0
;
iProv
<
ARRAY_SIZE
(
szProviders
);
iProv
++
)
...
...
@@ -4016,6 +4231,7 @@ START_TEST(rsaenh)
test_import_hmac
();
test_enum_container
();
if
(
!
BASE_PROV
)
test_key_derivation
(
STRONG_PROV
?
"STRONG"
:
"ENH"
);
test_rc2_import
();
clean_up_base_environment
();
}
...
...
@@ -4026,10 +4242,12 @@ START_TEST(rsaenh)
test_rsa_round_trip
();
if
(
!
init_aes_environment
())
return
;
trace
(
"Testing AES provider.
\n
"
);
test_aes
(
128
);
test_aes
(
192
);
test_aes
(
256
);
test_sha2
();
test_key_derivation
(
"AES"
);
test_rc2_import
();
clean_up_aes_environment
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment