diff -ur openssl-OpenSSL_1_0_2g/crypto/srp/srp.h openssl-work/crypto/srp/srp.h
--- openssl-OpenSSL_1_0_2g/crypto/srp/srp.h	2016-03-01 21:36:54.000000000 +0800
+++ openssl-work/crypto/srp/srp.h	2016-03-10 16:35:45.000000000 +0800
@@ -161,6 +161,7 @@
 BIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v);
 int SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N);
 BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N);
+BIGNUM* SRP_Calc_M2(BIGNUM* A, BIGNUM* M1, BIGNUM* K);
 
 /* client side .... */
 BIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass);
@@ -168,6 +169,7 @@
 BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x,
                             BIGNUM *a, BIGNUM *u);
 int SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N);
+BIGNUM* SRP_Calc_M1(BIGNUM *N, BIGNUM* g, const char* user, BIGNUM *s, BIGNUM* A, BIGNUM* B, BIGNUM* K);
 
 #  define SRP_MINIMAL_N 1024
 
diff -ur openssl-OpenSSL_1_0_2g/crypto/srp/srp_lib.c openssl-work/crypto/srp/srp_lib.c
--- openssl-OpenSSL_1_0_2g/crypto/srp/srp_lib.c	2016-03-01 21:36:54.000000000 +0800
+++ openssl-work/crypto/srp/srp_lib.c	2016-03-10 16:37:59.000000000 +0800
@@ -354,4 +354,80 @@
     }
     return NULL;
 }
+
+BIGNUM* SRP_Calc_M1(BIGNUM* N, BIGNUM* g, const char* username, BIGNUM* s, BIGNUM* A, BIGNUM* B, BIGNUM* K)
+{
+    /* H[H(N) XOR H(g) | H(username) | s | A | B | K] */
+    unsigned char* tmp = NULL;
+    unsigned char dig[SHA_DIGEST_LENGTH];
+    unsigned char digg[SHA_DIGEST_LENGTH];
+    EVP_MD_CTX ctxt;
+
+    if((tmp = OPENSSL_malloc(BN_num_bytes(N))) == NULL)
+    {
+        return NULL;
+    }
+
+    // H(N)
+    EVP_MD_CTX_init(&ctxt);
+    EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
+    BN_bn2bin(N, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(N));
+    EVP_DigestFinal_ex(&ctxt, dig, NULL);
+
+    EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
+    BN_bn2bin(g, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(g));
+    EVP_DigestFinal_ex(&ctxt, digg, NULL);
+
+    // H(N) ^ H(g)
+    int i = 0;
+    for(; i < SHA_DIGEST_LENGTH; ++i)
+    {
+        dig[i] ^= digg[i];
+    }
+
+    EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
+    EVP_DigestUpdate(&ctxt, dig, sizeof(dig));
+    BN_bn2bin(s, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(s));
+    BN_bn2bin(A, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(A));
+    BN_bn2bin(B, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(B));
+    BN_bn2bin(K, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(K));
+    EVP_DigestFinal_ex(&ctxt, dig, NULL);
+    EVP_MD_CTX_cleanup(&ctxt);
+
+    OPENSSL_free(tmp);
+    return BN_bin2bn(dig, sizeof(dig), NULL);
+}
+
+BIGNUM* SRP_Calc_M2(BIGNUM* A, BIGNUM* M1, BIGNUM* K)
+{
+    /* H(A | M1 | K) */
+    unsigned char* tmp = NULL;
+    unsigned char dig[SHA_DIGEST_LENGTH];
+    EVP_MD_CTX ctxt;
+
+    if((tmp = OPENSSL_malloc(BN_num_bytes(K))) == NULL)
+    {
+        return NULL;
+    }
+
+    EVP_MD_CTX_init(&ctxt);
+    EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
+    BN_bn2bin(A, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(A));
+    BN_bn2bin(M1, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(M1));
+    BN_bn2bin(K, tmp);
+    EVP_DigestUpdate(&ctxt, tmp, BN_num_bytes(K));
+    EVP_DigestFinal_ex(&ctxt, dig, NULL);
+    EVP_MD_CTX_cleanup(&ctxt);
+
+    OPENSSL_free(tmp);
+    return BN_bin2bn(dig, sizeof(dig), NULL);
+}
 #endif
