Quellcode durchsuchen

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

toddouska vor 13 Jahren
Ursprung
Commit
948a901cfc
10 geänderte Dateien mit 205 neuen und 31 gelöschten Zeilen
  1. 29 0
      certs/dh2048.pem
  2. 1 0
      certs/include.am
  3. 8 1
      ctaocrypt/src/asn.c
  4. 6 2
      cyassl/internal.h
  5. 11 1
      cyassl/ssl.h
  6. 28 0
      cyassl/test.h
  7. 5 1
      examples/echoserver/echoserver.c
  8. 5 1
      examples/server/server.c
  9. 19 4
      src/internal.c
  10. 93 21
      src/ssl.c

+ 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;