Procházet zdrojové kódy

add DH param setting by file and buffer, by ctx too

toddouska před 12 roky
rodič
revize
948a901cfc

+ 29 - 0
certs/dh2048.pem

@@ -0,0 +1,29 @@
+Diffie-Hellman-Parameters: (2048 bit)
+    prime:
+        00:b0:a1:08:06:9c:08:13:ba:59:06:3c:bc:30:d5:
+        f5:00:c1:4f:44:a7:d6:ef:4a:c6:25:27:1c:e8:d2:
+        96:53:0a:5c:91:dd:a2:c2:94:84:bf:7d:b2:44:9f:
+        9b:d2:c1:8a:c5:be:72:5c:a7:e7:91:e6:d4:9f:73:
+        07:85:5b:66:48:c7:70:fa:b4:ee:02:c9:3d:9a:4a:
+        da:3d:c1:46:3e:19:69:d1:17:46:07:a3:4d:9f:2b:
+        96:17:39:6d:30:8d:2a:f3:94:d3:75:cf:a0:75:e6:
+        f2:92:1f:1a:70:05:aa:04:83:57:30:fb:da:76:93:
+        38:50:e8:27:fd:63:ee:3c:e5:b7:c8:09:ae:6f:50:
+        35:8e:84:ce:4a:00:e9:12:7e:5a:31:d7:33:fc:21:
+        13:76:cc:16:30:db:0c:fc:c5:62:a7:35:b8:ef:b7:
+        b0:ac:c0:36:f6:d9:c9:46:48:f9:40:90:00:2b:1b:
+        aa:6c:e3:1a:c3:0b:03:9e:1b:c2:46:e4:48:4e:22:
+        73:6f:c3:5f:d4:9a:d6:30:07:48:d6:8c:90:ab:d4:
+        f6:f1:e3:48:d3:58:4b:a6:b9:cd:29:bf:68:1f:08:
+        4b:63:86:2f:5c:6b:d6:b6:06:65:f7:a6:dc:00:67:
+        6b:bb:c3:a9:41:83:fb:c7:fa:c8:e2:1e:7e:af:00:
+        3f:93
+    generator: 2 (0x2)
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEAsKEIBpwIE7pZBjy8MNX1AMFPRKfW70rGJScc6NKWUwpckd2iwpSE
+v32yRJ+b0sGKxb5yXKfnkebUn3MHhVtmSMdw+rTuAsk9mkraPcFGPhlp0RdGB6NN
+nyuWFzltMI0q85TTdc+gdebykh8acAWqBINXMPvadpM4UOgn/WPuPOW3yAmub1A1
+joTOSgDpEn5aMdcz/CETdswWMNsM/MVipzW477ewrMA29tnJRkj5QJAAKxuqbOMa
+wwsDnhvCRuRITiJzb8Nf1JrWMAdI1oyQq9T28eNI01hLprnNKb9oHwhLY4YvXGvW
+tgZl96bcAGdru8OpQYP7x/rI4h5+rwA/kwIBAg==
+-----END DH PARAMETERS-----

+ 1 - 0
certs/include.am

@@ -10,6 +10,7 @@ certs_DATA+= \
 	     certs/client-key.pem \
 	     certs/ecc-key.pem \
 	     certs/ntru-cert.pem \
+	     certs/dh2048.pem \
 	     certs/server-cert.pem \
 	     certs/server-ecc.pem \
 	     certs/server-keyEnc.pem \

+ 8 - 1
ctaocrypt/src/asn.c

@@ -909,18 +909,24 @@ int DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
                  byte* g, word32* gInOutSz)
 {
     word32 i = 0;
-    byte   b = input[i++];
+    byte   b;
     int    length;
 
     if (GetSequence(input, &i, &length, inSz) < 0)
         return ASN_PARSE_E;
 
+    b = input[i++];
     if (b != ASN_INTEGER)
         return ASN_PARSE_E;
 
     if (GetLength(input, &i, &length, inSz) < 0)
         return ASN_PARSE_E;
 
+    if ( (b = input[i++]) == 0x00)
+        length--;
+    else
+        i--;
+
     if (length <= *pInOutSz) {
         XMEMCPY(p, &input[i], length);
         *pInOutSz = length;
@@ -930,6 +936,7 @@ int DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
 
     i += length;
 
+    b = input[i++];
     if (b != ASN_INTEGER)
         return ASN_PARSE_E;
 

+ 6 - 2
cyassl/internal.h

@@ -290,6 +290,7 @@ enum Misc {
     ALERT_SIZE     =  2,       /* level + description     */
     REQUEST_HEADER =  2,       /* always use 2 bytes      */
     VERIFY_HEADER  =  2,       /* always use 2 bytes      */
+    MAX_DH_SIZE    = 513,      /* 4096 bit plus possible leading 0 */
 
     MAX_SUITE_SZ = 200,        /* 100 suites for now! */
     RAN_LEN      = 32,         /* random length           */
@@ -569,6 +570,8 @@ struct CYASSL_CTX {
     buffer      certChain;
                  /* chain after self, in DER, with leading size for each cert */
     buffer      privateKey;
+    buffer      serverDH_P;
+    buffer      serverDH_G;
     Signer*     caList;           /* CYASSL_CTX owns this, SSL will reference */
     Suites      suites;
     void*       heap;             /* for user memory overrides */
@@ -843,8 +846,8 @@ typedef struct Buffers {
     buffer          certChain;              /* CYASSL_CTX owns */
                  /* chain after self, in DER, with leading size for each cert */
     buffer          domainName;             /* for client check */
-    buffer          serverDH_P;
-    buffer          serverDH_G;
+    buffer          serverDH_P;             /* CYASSL_CTX owns, unless we own */
+    buffer          serverDH_G;             /* CYASSL_CTX owns, unless we own */
     buffer          serverDH_Pub;
     buffer          serverDH_Priv;
     bufferStatic    inputBuffer;
@@ -856,6 +859,7 @@ typedef struct Buffers {
                                               when got WANT_WRITE            */
     byte            weOwnCert;             /* SSL own cert flag */
     byte            weOwnKey;              /* SSL own key  flag */
+    byte            weOwnDH;               /* SSL own dh (p,g)  flag */
 } Buffers;
 
 

+ 11 - 1
cyassl/ssl.h

@@ -672,7 +672,7 @@ CYASSL_API char*  CyaSSL_X509_get_subjectCN(CYASSL_X509*);
 /* connect enough to get peer cert */
 CYASSL_API int  CyaSSL_connect_cert(CYASSL* ssl);
 
-/* server CTX Diffie-Hellman parameters */
+/* server Diffie-Hellman parameters */
 CYASSL_API int  CyaSSL_SetTmpDH(CYASSL*, unsigned char* p, int pSz,
                                 unsigned char* g, int gSz);
 CYASSL_API int  CyaSSL_SetTmpDH_buffer(CYASSL*, unsigned char* b, long sz,
@@ -681,6 +681,16 @@ CYASSL_API int  CyaSSL_SetTmpDH_buffer(CYASSL*, unsigned char* b, long sz,
     CYASSL_API int  CyaSSL_SetTmpDH_file(CYASSL*, const char* f, int format);
 #endif
 
+/* server ctx Diffie-Hellman parameters */
+CYASSL_API int  CyaSSL_CTX_SetTmpDH(CYASSL_CTX*, unsigned char* p, int pSz,
+                                    unsigned char* g, int gSz);
+CYASSL_API int  CyaSSL_CTX_SetTmpDH_buffer(CYASSL_CTX*, unsigned char* b,
+                                           long sz, int format);
+#ifndef NO_FILESYSTEM
+    CYASSL_API int  CyaSSL_CTX_SetTmpDH_file(CYASSL_CTX*, const char* f,
+                                             int format);
+#endif
+
 /* keyblock size in bytes or -1 */
 CYASSL_API int CyaSSL_get_keyblock_size(CYASSL*);
 CYASSL_API int CyaSSL_get_keys(CYASSL*,unsigned char** ms, unsigned int* msLen,

+ 28 - 0
cyassl/test.h

@@ -106,6 +106,7 @@ static const char* cliCert  = "./certs/client-cert.pem";
 static const char* cliKey   = "./certs/client-key.pem";
 static const char* ntruCert = "./certs/ntru-cert.pem";
 static const char* ntruKey  = "./certs/ntru-key.raw";
+static const char* dhParam  = "./certs/dh2048.pem";
 
 typedef struct tcp_ready {
     int ready;              /* predicate */
@@ -594,6 +595,33 @@ static INLINE void SetDH(SSL* ssl)
     CyaSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g));
 }
 
+static INLINE void SetDHCtx(SSL_CTX* ctx)
+{
+    /* dh1024 p */
+    static unsigned char p[] =
+    {
+        0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
+        0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
+        0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
+        0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
+        0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
+        0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
+        0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
+        0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
+        0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
+        0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
+        0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
+    };
+
+    /* dh1024 g */
+    static unsigned char g[] =
+    {
+      0x02,
+    };
+
+    CyaSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g));
+}
+
 #ifdef USE_WINDOWS_API 
 
 /* do back x number of directories */

+ 5 - 1
examples/echoserver/echoserver.c

@@ -149,7 +149,11 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
         ssl = SSL_new(ctx);
         if (ssl == NULL) err_sys("SSL_new failed");
         SSL_set_fd(ssl, clientfd);
-        SetDH(ssl);
+        #ifdef NO_FILESYSTEM
+            SetDH(ssl);
+        #else
+            CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM);
+        #endif
         if (SSL_accept(ssl) != SSL_SUCCESS) {
             printf("SSL_accept failed\n");
             SSL_free(ssl);

+ 5 - 1
examples/server/server.c

@@ -150,7 +150,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
 
     SSL_set_fd(ssl, clientfd);
 #ifdef NO_PSK
-    SetDH(ssl);   /* will repick suites with DHE, higher priority than PSK */
+    #ifdef NO_FILESYSTEM
+        SetDH(ssl);  /* will repick suites with DHE, higher priority than PSK */
+    #else
+        CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM);
+    #endif
 #endif
 
 #ifdef NON_BLOCKING

+ 19 - 4
src/internal.c

@@ -328,6 +328,8 @@ void InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
     ctx->certificate.buffer = 0;
     ctx->certChain.buffer   = 0;
     ctx->privateKey.buffer  = 0;
+    ctx->serverDH_P.buffer  = 0;
+    ctx->serverDH_G.buffer  = 0;
     ctx->haveDH             = 0;
     ctx->haveNTRU           = 0;    /* start off */
     ctx->haveECDSA          = 0;    /* start off */
@@ -384,6 +386,8 @@ void InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
 /* In case contexts are held in array and don't want to free actual ctx */
 void SSL_CtxResourceFree(CYASSL_CTX* ctx)
 {
+    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
     XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
     XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
     XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
@@ -681,7 +685,10 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
     ssl->options.closeNotify  = 0;
     ssl->options.sentNotify   = 0;
     ssl->options.usingCompression = 0;
-    ssl->options.haveDH    = ctx->haveDH;
+    if (ssl->options.side == SERVER_END)
+        ssl->options.haveDH = ctx->haveDH;
+    else
+        ssl->options.haveDH = 0;
     ssl->options.haveNTRU  = ctx->haveNTRU;
     ssl->options.haveECDSA = ctx->haveECDSA;
     ssl->options.havePeerCert = 0; 
@@ -727,12 +734,17 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
     ssl->options.quietShutdown = ctx->quietShutdown;
     ssl->options.certOnly = 0;
 
-    /* CYASSL_CTX still owns certificate, certChain, key, and caList buffers */
+    /* ctx still owns certificate, certChain, key, dh, and caList buffers */
     ssl->buffers.certificate = ctx->certificate;
     ssl->buffers.certChain = ctx->certChain;
     ssl->buffers.key = ctx->privateKey;
+    if (ssl->options.side == SERVER_END) {
+        ssl->buffers.serverDH_P = ctx->serverDH_P;
+        ssl->buffers.serverDH_G = ctx->serverDH_G;
+    }
     ssl->buffers.weOwnCert = 0;
     ssl->buffers.weOwnKey  = 0;
+    ssl->buffers.weOwnDH   = 0;
 
 #ifdef OPENSSL_EXTRA
     ssl->peerCert.issuer.sz    = 0;
@@ -810,8 +822,11 @@ void SSL_ResourceFree(CYASSL* ssl)
 {
     XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
     XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
-    XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
-    XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+    /* parameters (p,g) may be owned by ctx */
+    if (ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+    }
     XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
 
     /* CYASSL_CTX always owns certChain */

+ 93 - 21
src/ssl.c

@@ -167,9 +167,6 @@ int CyaSSL_negotiate(CYASSL* ssl)
 }
 
 
-
-
-
 /* server Diffie-Hellman parameters */
 int CyaSSL_SetTmpDH(CYASSL* ssl, unsigned char* p, int pSz, unsigned char* g,
                     int gSz)
@@ -182,11 +179,12 @@ int CyaSSL_SetTmpDH(CYASSL* ssl, unsigned char* p, int pSz, unsigned char* g,
     if (ssl->options.side != SERVER_END)
         return SIDE_ERROR;
 
-    if (ssl->buffers.serverDH_P.buffer)
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH)
         XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH);
-    if (ssl->buffers.serverDH_G.buffer)
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH)
         XFREE(ssl->buffers.serverDH_G.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH);
 
+    ssl->buffers.weOwnDH = 1;  /* SSL owns now */
     ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->ctx->heap,
                                                     DYNAMIC_TYPE_DH);
     if (ssl->buffers.serverDH_P.buffer == NULL)
@@ -212,6 +210,7 @@ int CyaSSL_SetTmpDH(CYASSL* ssl, unsigned char* p, int pSz, unsigned char* g,
     InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH,
                havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA,
                ssl->ctx->method->side);
+
     CYASSL_LEAVE("CyaSSL_SetTmpDH", 0);
     return 0;
 }
@@ -534,8 +533,9 @@ int AddCA(CYASSL_CTX* ctx, buffer der)
             dynamicType = (type == CA_TYPE) ? DYNAMIC_TYPE_CA :
                                               DYNAMIC_TYPE_CERT;
         } else if (type == DH_PARAM_TYPE) {
-
-
+            XSTRNCPY(header, "-----BEGIN DH PARAMETERS-----", sizeof(header));
+            XSTRNCPY(footer, "-----END DH PARAMETERS-----", sizeof(footer));
+            dynamicType = DYNAMIC_TYPE_KEY;
         } else {
             XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
             XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----", sizeof(footer));
@@ -640,7 +640,8 @@ int AddCA(CYASSL_CTX* ctx, buffer der)
         else
             return SSL_BAD_FILE;
 
-        info->consumed = (long)(consumedEnd - (char*)buff);
+        if (info)
+            info->consumed = (long)(consumedEnd - (char*)buff);
 
         /* set up der buffer */
         neededSz = (long)(footerEnd - headerEnd);
@@ -1189,16 +1190,17 @@ int CyaSSL_use_certificate_chain_file(CYASSL* ssl, const char* file)
 }
 
 
-/* server Diffie-Hellman parameters */
-int CyaSSL_SetTmpDH_buffer(CYASSL* ssl, unsigned char* buf, long sz, int format)
+/* server wrapper for ctx or ssl Diffie-Hellman parameters */
+static int CyaSSL_SetTmpDH_buffer_wrapper(CYASSL_CTX* ctx, CYASSL* ssl,
+                                        unsigned char* buf, long sz, int format)
 {
     buffer der;
     int    ret;
     int    weOwnDer = 0;
-    byte   p[1024];
-    byte   g[1024];
-    int    pSz = sizeof(p);
-    int    gSz = sizeof(g);
+    byte   p[MAX_DH_SIZE];
+    byte   g[MAX_DH_SIZE];
+    word32 pSz = sizeof(p);
+    word32 gSz = sizeof(g);
 
     der.buffer = buf;
     der.length = sz;
@@ -1207,7 +1209,8 @@ int CyaSSL_SetTmpDH_buffer(CYASSL* ssl, unsigned char* buf, long sz, int format)
         return SSL_BAD_FILETYPE;
 
     if (format == SSL_FILETYPE_PEM) {
-        ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, NULL, NULL, NULL);
+        der.buffer = NULL;
+        ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL,NULL);
         if (ret < 0) {
             XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
             return ret;
@@ -1217,8 +1220,12 @@ int CyaSSL_SetTmpDH_buffer(CYASSL* ssl, unsigned char* buf, long sz, int format)
 
     if (DhParamsLoad(der.buffer, der.length, p, &pSz, g, &gSz) < 0)
         ret = SSL_BAD_FILETYPE;
-    else
-        ret = CyaSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+    else {
+        if (ssl)
+            ret = CyaSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+        else
+            ret = CyaSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+    }
 
     if (weOwnDer)
         XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
@@ -1226,11 +1233,26 @@ int CyaSSL_SetTmpDH_buffer(CYASSL* ssl, unsigned char* buf, long sz, int format)
     return ret;
 }
 
+/* server Diffie-Hellman parameters */
+int CyaSSL_SetTmpDH_buffer(CYASSL* ssl, unsigned char* buf, long sz, int format)
+{
+    return CyaSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
+}
+
+
+/* server ctx Diffie-Hellman parameters */
+int CyaSSL_CTX_SetTmpDH_buffer(CYASSL_CTX* ctx, unsigned char* buf, long sz,
+                               int format)
+{
+    return CyaSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
+}
+
 
 #if !defined(NO_FILESYSTEM)
 
 /* server Diffie-Hellman parameters */
-int CyaSSL_SetTmpDH_file(CYASSL* ssl, const char* fname, int format)
+static int CyaSSL_SetTmpDH_file_wrapper(CYASSL_CTX* ctx, CYASSL* ssl,
+                                        const char* fname, int format)
 {
     byte   staticBuffer[FILE_BUFFER_SIZE];
     byte*  myBuffer = staticBuffer;
@@ -1256,16 +1278,33 @@ int CyaSSL_SetTmpDH_file(CYASSL* ssl, const char* fname, int format)
 
     if ( (ret = XFREAD(myBuffer, sz, 1, file)) < 0)
         ret = SSL_BAD_FILE;
-    else
-        ret = CyaSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
+    else {
+        if (ssl)
+            ret = CyaSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
+        else
+            ret = CyaSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format);
+    }
 
     XFCLOSE(file);
     if (dynamic) XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
 
     return ret;
+}
 
+/* server Diffie-Hellman parameters */
+int CyaSSL_SetTmpDH_file(CYASSL* ssl, const char* fname, int format)
+{
+    return CyaSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
 }
 
+
+/* server Diffie-Hellman parameters */
+int CyaSSL_CTX_SetTmpDH_file(CYASSL_CTX* ctx, const char* fname, int format)
+{
+    return CyaSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
+}
+
+
 #endif /* !NO_FILESYSTEM */
 #endif /* OPENSSL_EXTRA */
 
@@ -2080,7 +2119,7 @@ int AddSession(CYASSL* ssl)
 
         for (i = 0; i < SESSION_ROWS; i++) {
             double diff = SessionCache[i].totalCount - E;
-            diff *= diff;                /* sqaure    */
+            diff *= diff;                /* square    */
             diff /= E;                   /* normalize */
 
             chiSquare += diff;
@@ -3636,6 +3675,39 @@ int CyaSSL_set_compression(CYASSL* ssl)
     }
 
 
+    /* server ctx Diffie-Hellman parameters */
+    int CyaSSL_CTX_SetTmpDH(CYASSL_CTX* ctx, unsigned char* p, int pSz,
+                            unsigned char* g, int gSz)
+    {
+        CYASSL_ENTER("CyaSSL_CTX_SetTmpDH");
+        if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
+
+        XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+        XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+
+        ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap,DYNAMIC_TYPE_DH);
+        if (ctx->serverDH_P.buffer == NULL)
+            return MEMORY_E;
+
+        ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap,DYNAMIC_TYPE_DH);
+        if (ctx->serverDH_G.buffer == NULL) {
+            XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+            return MEMORY_E;
+        }
+
+        ctx->serverDH_P.length = pSz;
+        ctx->serverDH_G.length = gSz;
+
+        XMEMCPY(ctx->serverDH_P.buffer, p, pSz);
+        XMEMCPY(ctx->serverDH_G.buffer, g, gSz);
+
+        ctx->haveDH = 1;
+
+        CYASSL_LEAVE("CyaSSL_CTX_SetTmpDH", 0);
+        return 0;
+    }
+
+
     char* CyaSSL_CIPHER_description(CYASSL_CIPHER* cipher, char* in, int len)
     {
         (void)cipher;