added check for allowed minimum DH key size

This commit is contained in:
John Safranek 2015-05-21 10:11:21 -07:00
parent 50a80bbcd2
commit 64602d1969
13 changed files with 181 additions and 3 deletions

View File

@ -1,3 +1,9 @@
crit-cert.pem:
Simple self-signed certificate with critical Basic Constraints and Key Usage
extensions.
dh512.pem, dh512.der:
512-bit DH parameters. Used for testing the rejection of lower-bit sized DH
keys.
dh1024.pem, dh1024.der:
1024-bit DH parameters. Used for testing the rejection of lower-bit sized DH
keys.

BIN
certs/test/dh1024.der Normal file

Binary file not shown.

17
certs/test/dh1024.pem Normal file
View File

@ -0,0 +1,17 @@
DH Parameters: (1024 bit)
prime:
00:ee:73:a6:93:be:a9:b8:5f:52:b9:9c:d4:a8:0f:
8d:f9:b0:53:29:a9:25:06:0e:95:dd:f5:89:c8:6b:
09:ae:94:1c:62:35:05:39:ab:6d:46:c5:b2:a2:fd:
a0:e1:ba:01:a5:00:4f:7f:44:e5:74:81:8b:3a:2e:
fa:ea:fe:f6:c3:18:11:ca:fd:ee:8b:9c:9e:0d:1a:
5a:57:77:74:63:91:e7:51:bb:6d:79:93:e2:b4:5c:
fa:21:21:ff:5d:b3:e7:5c:92:08:ca:cb:4e:e7:8c:
f3:1c:21:8c:44:8c:6d:31:60:7a:e6:37:15:79:1b:
1d:5d:c3:56:c3:a0:4a:8d:03
generator: 2 (0x2)
-----BEGIN DH PARAMETERS-----
MIGHAoGBAO5zppO+qbhfUrmc1KgPjfmwUympJQYOld31ichrCa6UHGI1BTmrbUbF
sqL9oOG6AaUAT39E5XSBizou+ur+9sMYEcr97oucng0aWld3dGOR51G7bXmT4rRc
+iEh/12z51ySCMrLTueM8xwhjESMbTFgeuY3FXkbHV3DVsOgSo0DAgEC
-----END DH PARAMETERS-----

BIN
certs/test/dh512.der Normal file

Binary file not shown.

12
certs/test/dh512.pem Normal file
View File

@ -0,0 +1,12 @@
DH Parameters: (512 bit)
prime:
00:87:76:23:99:e1:df:db:6a:43:8e:30:2b:4f:63:
53:05:77:ce:80:02:8e:b1:a8:44:4f:30:d8:c9:45:
d9:cd:65:e3:4b:2d:b6:eb:77:a3:26:ea:4d:03:84:
d9:d7:b6:6a:b6:dd:51:97:66:c1:77:e6:6b:ed:19:
91:45:c5:27:b3
generator: 2 (0x2)
-----BEGIN DH PARAMETERS-----
MEYCQQCHdiOZ4d/bakOOMCtPY1MFd86AAo6xqERPMNjJRdnNZeNLLbbrd6Mm6k0D
hNnXtmq23VGXZsF35mvtGZFFxSezAgEC
-----END DH PARAMETERS-----

View File

@ -130,6 +130,10 @@ static void Usage(void)
printf("-c <file> Certificate file, default %s\n", cliCert);
printf("-k <file> Key file, default %s\n", cliKey);
printf("-A <file> Certificate Authority file, default %s\n", caCert);
#ifndef NO_DH
printf("-Z <num> Minimum DH key bits, default %d\n",
DEFAULT_MIN_DHKEY_BITS);
#endif
printf("-b <num> Benchmark <num> connections and print stats\n");
printf("-s Use pre Shared keys\n");
printf("-t Track wolfSSL memory use\n");
@ -224,6 +228,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int atomicUser = 0;
int pkCallbacks = 0;
int overrideDateErrors = 0;
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
char* cipherList = NULL;
const char* verifyCert = caCert;
const char* ourCert = cliCert;
@ -269,11 +274,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void)useClientCert;
(void)overrideDateErrors;
(void)disableCRL;
(void)minDhKeyBits;
StackTrap();
while ((ch = mygetopt(argc, argv,
"?gdDusmNrwRitfxXUPCh:p:v:l:A:c:k:b:zS:L:ToO:a"))
"?gdDusmNrwRitfxXUPCh:p:v:l:A:c:k:Z:b:zS:L:ToO:a"))
!= -1) {
switch (ch) {
case '?' :
@ -375,6 +381,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
ourKey = myoptarg;
break;
case 'Z' :
#ifndef NO_DH
minDhKeyBits = atoi(myoptarg);
if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
Usage();
exit(MY_EX_USAGE);
}
#endif
break;
case 'b' :
benchmark = atoi(myoptarg);
if (benchmark < 0 || benchmark > 1000000) {
@ -570,6 +586,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (fewerPackets)
wolfSSL_CTX_set_group_messages(ctx);
#ifndef NO_DH
wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
#endif
if (usePsk) {
#ifndef NO_PSK
wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);

View File

@ -131,6 +131,11 @@ static void Usage(void)
printf("-c <file> Certificate file, default %s\n", svrCert);
printf("-k <file> Key file, default %s\n", svrKey);
printf("-A <file> Certificate Authority file, default %s\n", cliCert);
#ifndef NO_DH
printf("-D <file> Diffie-Hellman Params file, default %s\n", dhParam);
printf("-Z <num> Minimum DH key bits, default %d\n",
DEFAULT_MIN_DHKEY_BITS);
#endif
printf("-d Disable client cert check\n");
printf("-b Bind to any interface instead of localhost only\n");
printf("-s Use pre Shared keys\n");
@ -184,11 +189,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
int serverReadyFile = 0;
int wc_shutdown = 0;
int resume = 0; /* do resume, and resume count */
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
int ret;
char* cipherList = NULL;
const char* verifyCert = cliCert;
const char* ourCert = svrCert;
const char* ourKey = svrKey;
const char* ourDhParam = dhParam;
int argc = ((func_args*)args)->argc;
char** argv = ((func_args*)args)->argv;
@ -213,15 +220,17 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
(void)needDH;
(void)ourKey;
(void)ourCert;
(void)ourDhParam;
(void)verifyCert;
(void)useNtruKey;
(void)doCliCertCheck;
(void)minDhKeyBits;
#ifdef CYASSL_TIRTOS
fdOpenSession(Task_self());
#endif
while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPp:v:l:A:c:k:S:oO:"))
while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPp:v:l:A:c:k:Z:S:oO:D:"))
!= -1) {
switch (ch) {
case '?' :
@ -310,6 +319,22 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
ourKey = myoptarg;
break;
case 'D' :
#ifndef NO_DH
ourDhParam = myoptarg;
#endif
break;
case 'Z' :
#ifndef NO_DH
minDhKeyBits = atoi(myoptarg);
if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
Usage();
exit(MY_EX_USAGE);
}
#endif
break;
case 'N':
nonBlocking = 1;
break;
@ -451,6 +476,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
}
#endif
#ifndef NO_DH
wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
#endif
#ifdef HAVE_NTRU
if (useNtruKey) {
if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
@ -579,7 +608,7 @@ while (1) { /* allow resume option */
SSL_set_fd(ssl, clientfd);
if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) {
#if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM);
CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM);
#elif !defined(NO_DH)
SetDH(ssl); /* repick suites with DHE, higher priority than PSK */
#endif

View File

@ -372,6 +372,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
return BAD_MUTEX_E;
}
#ifndef NO_DH
ctx->minDhKeySz = MIN_DHKEY_SZ;
#endif
#ifdef HAVE_ECC
ctx->eccTempKeySz = ECDHE_SIZE;
#endif
@ -1537,6 +1541,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
ssl->options.handShakeState = NULL_STATE;
ssl->options.processReply = doProcessInit;
#ifndef NO_DH
ssl->options.minDhKeySz = ctx->minDhKeySz;
#endif
#ifdef WOLFSSL_DTLS
ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT;
ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX;
@ -8024,6 +8032,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case BAD_TICKET_ENCRYPT:
return "Bad user ticket callback encrypt Error";
case DH_KEY_SIZE_E:
return "DH key too small Error";
default :
return "unknown error number";
}
@ -9755,6 +9766,12 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;
if (length < ssl->options.minDhKeySz) {
WOLFSSL_MSG("Server using a DH key that is too small");
SendAlert(ssl, alert_fatal, handshake_failure);
return DH_KEY_SIZE_E;
}
ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
@ -9766,6 +9783,8 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
*inOutIdx += length;
ssl->options.dhKeySz = length;
/* g */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
@ -9885,6 +9904,12 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;
if (length < ssl->options.minDhKeySz) {
WOLFSSL_MSG("Server using a DH key that is too small");
SendAlert(ssl, alert_fatal, handshake_failure);
return DH_KEY_SIZE_E;
}
ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
@ -9896,6 +9921,8 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
*inOutIdx += length;
ssl->options.dhKeySz = length;
/* g */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;

View File

@ -438,6 +438,9 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
WOLFSSL_ENTER("wolfSSL_SetTmpDH");
if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
if (pSz < ssl->options.minDhKeySz)
return DH_KEY_SIZE_E;
if (ssl->options.side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
@ -487,6 +490,9 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
if (pSz < ctx->minDhKeySz)
return DH_KEY_SIZE_E;
XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
@ -3894,6 +3900,35 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
}
int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
{
if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
return BAD_FUNC_ARG;
ctx->minDhKeySz = keySz / 8;
return SSL_SUCCESS;
}
int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
{
if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
return BAD_FUNC_ARG;
ssl->options.minDhKeySz = keySz / 8;
return SSL_SUCCESS;
}
int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
return (ssl->options.dhKeySz * 8);
}
#endif /* NO_DH */

View File

@ -133,6 +133,8 @@ enum wolfSSL_ErrorCodes {
BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */
BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */
DH_KEY_SIZE_E = -401, /* DH Key too small */
/* add strings to SetErrorString !!!!! */
/* begin negotiation parameter errors */

View File

@ -895,6 +895,20 @@ enum Misc {
COPY = 1 /* should we copy static buffer for write */
};
#ifndef WOLFSSL_MIN_DHKEY_BITS
#ifdef WOLFSSL_MAX_STRENGTH
#define WOLFSSL_MIN_DHKEY_BITS 2048
#else
#define WOLFSSL_MIN_DHKEY_BITS 1024
#endif
#endif
#if (WOLFSSL_MIN_DHKEY_BITS % 8)
#error DH minimum bit size must be multiple of 8
#endif
#define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8)
#ifdef SESSION_INDEX
/* Shift values for making a session index */
#define SESSIDX_ROW_SHIFT 4
@ -1508,6 +1522,9 @@ struct WOLFSSL_CTX {
byte quietShutdown; /* don't send close notify */
byte groupMessages; /* group handshake messages before sending */
byte minDowngrade; /* minimum downgrade version */
#ifndef NO_DH
word16 minDhKeySz; /* minimum DH key size */
#endif
CallbackIORecv CBIORecv;
CallbackIOSend CBIOSend;
#ifdef WOLFSSL_DTLS
@ -1916,6 +1933,10 @@ typedef struct Options {
byte minDowngrade; /* minimum downgrade version */
byte connectState; /* nonblocking resume */
byte acceptState; /* nonblocking resume */
#ifndef NO_DH
word16 minDhKeySz; /* minimum DH key size */
word16 dhKeySz; /* actual DH key size */
#endif
} Options;

View File

@ -901,6 +901,10 @@ WOLFSSL_API int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char*
WOLFSSL_API int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f,
int format);
#endif
WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, unsigned short);
WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, unsigned short);
WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*);
#endif /* NO_DH */
WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short);

View File

@ -154,6 +154,11 @@
#define CLIENT_DEFAULT_VERSION 3
#define CLIENT_DTLS_DEFAULT_VERSION (-2)
#define CLIENT_INVALID_VERSION (-99)
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
#define DEFAULT_MIN_DHKEY_BITS 2048
#else
#define DEFAULT_MIN_DHKEY_BITS 1024
#endif
/* all certs relative to wolfSSL home directory now */
#define caCert "./certs/ca-cert.pem"