Skip to content

Commit e9889c6

Browse files
authored
Validate challenge (#402)
1 parent d267950 commit e9889c6

3 files changed

Lines changed: 31 additions & 8 deletions

File tree

lib/internal.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,18 @@ cipher_rc cipher_decrypt(cipher_key key, const unsigned char* in, uint32_t inlen
145145
return CIPHER_OK;
146146
}
147147

148+
uint32_t cipher_blocksize(cipher_key key) {
149+
if (key == NULL) {
150+
return 0;
151+
}
152+
DWORD size = 0;
153+
ULONG len = 0;
154+
if(!BCRYPT_SUCCESS(BCryptGetProperty(key->hKey, BCRYPT_BLOCK_LENGTH, &size, sizeof(size), &len, 0))) {
155+
return 0;
156+
}
157+
return size;
158+
}
159+
148160
#else
149161

150162
static int encrypt_ex(const uint8_t *in, uint8_t *out, int len,
@@ -242,6 +254,13 @@ cipher_rc cipher_decrypt(cipher_key key, const unsigned char* in, uint32_t inlen
242254
return rc;
243255
}
244256

257+
uint32_t cipher_blocksize(cipher_key key) {
258+
if(key) {
259+
return EVP_CIPHER_block_size(key->cipher);
260+
}
261+
return 0;
262+
}
263+
245264
#endif
246265

247266
bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key) {

lib/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ cipher_rc cipher_import_key(unsigned char algo, const unsigned char *keyraw, uin
181181
cipher_rc cipher_destroy_key(cipher_key key);
182182
cipher_rc cipher_encrypt(cipher_key key, const unsigned char *in, uint32_t inlen, unsigned char *out, uint32_t *outlen);
183183
cipher_rc cipher_decrypt(cipher_key key, const unsigned char *in, uint32_t inlen, unsigned char *out, uint32_t *outlen);
184+
uint32_t cipher_blocksize(cipher_key key);
184185

185186
pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key);
186187
bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key);

lib/ykpiv.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,11 @@ static ykpiv_rc _ykpiv_authenticate2(ykpiv_state *state, unsigned const char *ke
982982

983983
uint8_t *challenge = data + 4;
984984
uint32_t challenge_len = recv_len - 4;
985+
if(challenge_len != cipher_blocksize(mgm_key)) { // Only management key block size allowed
986+
DBG("%s: management key block size is %zu but received %u bytes challenge", ykpiv_strerror(YKPIV_PARSE_ERROR), cipher_blocksize(mgm_key), challenge_len);
987+
res = YKPIV_PARSE_ERROR;
988+
goto Cleanup;
989+
}
985990

986991
/* send a response to the cards challenge and a challenge of our own. */
987992
{
@@ -1007,26 +1012,23 @@ static ykpiv_rc _ykpiv_authenticate2(ykpiv_state *state, unsigned const char *ke
10071012
*dataptr++ = challenge_len;
10081013
challenge = dataptr;
10091014
if (PRNG_GENERAL_ERROR == _ykpiv_prng_generate(challenge, challenge_len)) {
1010-
DBG("Failed getting randomness for authentication.");
1015+
DBG("%s: Failed getting randomness for authentication.", ykpiv_strerror(YKPIV_RANDOMNESS_ERROR));
10111016
res = YKPIV_RANDOMNESS_ERROR;
10121017
goto Cleanup;
10131018
}
10141019
dataptr += challenge_len;
10151020
apdu.st.lc = (unsigned char)(dataptr - apdu.st.data);
10161021
recv_len = sizeof(data);
1017-
if ((res = _ykpiv_send_apdu(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK)
1018-
{
1022+
if ((res = _ykpiv_send_apdu(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
10191023
goto Cleanup;
10201024
}
10211025
else if (sw != SW_SUCCESS) {
10221026
res = YKPIV_AUTHENTICATION_ERROR;
10231027
goto Cleanup;
10241028
}
1025-
}
10261029

1027-
/* compare the response from the card with our challenge */
1028-
{
1029-
uint32_t out_len = challenge_len;
1030+
/* compare the response from the card with our challenge */
1031+
out_len = challenge_len;
10301032
drc = cipher_encrypt(mgm_key, challenge, challenge_len, challenge, &out_len);
10311033

10321034
if (drc != CIPHER_OK) {
@@ -2126,6 +2128,7 @@ ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, unsign
21262128

21272129
if (NULL == state) return YKPIV_GENERIC_ERROR;
21282130
if (NULL == response) return YKPIV_GENERIC_ERROR;
2131+
if (16 < response_len) return YKPIV_GENERIC_ERROR;
21292132

21302133
if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
21312134
/* note: do not select the applet here, as it resets the challenge state */
@@ -2141,7 +2144,7 @@ ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, unsign
21412144
}
21422145
}
21432146

2144-
/* send the response to the card and a challenge of our own. */
2147+
/* send the response to the card. */
21452148
APDU apdu = {0};
21462149
apdu.st.ins = YKPIV_INS_AUTHENTICATE;
21472150
apdu.st.p1 = metadata.algorithm;

0 commit comments

Comments
 (0)