summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2014-04-16 20:39:10 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2014-04-16 20:39:10 +0000
commit0b42c8e9442d14354d0c3dc40ea11ca81744f39f (patch)
treea88e15f71e751ac54787e17e12ad4420e78d46f2
parentd1c2971263880f9044c4db378bfe322cd012ab6b (diff)
add back SRP. i was being too greedy.
-rw-r--r--lib/libssl/s3_clnt.c106
-rw-r--r--lib/libssl/s3_lib.c209
-rw-r--r--lib/libssl/s3_srvr.c122
-rw-r--r--lib/libssl/ssl.h63
-rw-r--r--lib/libssl/ssl_asn1.c33
-rw-r--r--lib/libssl/ssl_ciph.c2
-rw-r--r--lib/libssl/ssl_lib.c6
-rw-r--r--lib/libssl/ssl_sess.c7
-rw-r--r--lib/libssl/ssl_txt.c6
-rw-r--r--lib/libssl/t1_lib.c50
10 files changed, 604 insertions, 0 deletions
diff --git a/lib/libssl/s3_clnt.c b/lib/libssl/s3_clnt.c
index 1589cdc21e4..88be294ab78 100644
--- a/lib/libssl/s3_clnt.c
+++ b/lib/libssl/s3_clnt.c
@@ -365,6 +365,15 @@ ssl3_connect(SSL *s)
ret = ssl3_get_server_done(s);
if (ret <= 0)
goto end;
+#ifndef OPENSSL_NO_SRP
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if ((ret = SRP_Calc_A_param(s)) <= 0) {
+ SSLerr(SSL_F_SSL3_CONNECT, SSL_R_SRP_A_CALC);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto end;
+ }
+ }
+#endif
if (s->s3->tmp.cert_req)
s->state = SSL3_ST_CW_CERT_A;
else
@@ -1290,6 +1299,76 @@ ssl3_get_key_exchange(SSL *s)
n -= param_len;
} else
#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (alg_k & SSL_kSRP) {
+ n2s(p, i);
+ param_len = i + 2;
+ if (param_len > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_N_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.N = BN_bin2bn(p, i, NULL))) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
+ }
+ p += i;
+
+ n2s(p, i);
+ param_len += i + 2;
+ if (param_len > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_G_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.g = BN_bin2bn(p, i, NULL))) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
+ }
+ p += i;
+
+ i = (unsigned int)(p[0]);
+ p++;
+ param_len += i + 1;
+ if (param_len > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_S_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.s = BN_bin2bn(p, i, NULL))) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
+ }
+ p += i;
+
+ n2s(p, i);
+ param_len += i + 2;
+ if (param_len > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_B_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.B = BN_bin2bn(p, i, NULL))) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
+ }
+ p += i;
+ n -= param_len;
+
+/* We must check if there is a certificate */
+#ifndef OPENSSL_NO_RSA
+ if (alg_a & SSL_aRSA)
+ pkey = X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+#else
+ if (0)
+;
+#endif
+#ifndef OPENSSL_NO_DSA
+ else if (alg_a & SSL_aDSS)
+ pkey = X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
+#endif
+ } else
+#endif /* !OPENSSL_NO_SRP */
#ifndef OPENSSL_NO_RSA
if (alg_k & SSL_kRSA) {
if ((rsa = RSA_new()) == NULL) {
@@ -2492,6 +2571,33 @@ ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_free(pub_key);
}
+#ifndef OPENSSL_NO_SRP
+ else if (alg_k & SSL_kSRP) {
+ if (s->srp_ctx.A != NULL) {
+ /* send off the data */
+ n = BN_num_bytes(s->srp_ctx.A);
+ s2n(n, p);
+ BN_bn2bin(s->srp_ctx.A, p);
+ n += 2;
+ } else {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (s->session->srp_username != NULL)
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((s->session->master_key_length = SRP_generate_client_master_secret(s, s->session->master_key)) < 0) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
#ifndef OPENSSL_NO_PSK
else if (alg_k & SSL_kPSK) {
char identity[PSK_MAX_IDENTITY_LEN];
diff --git a/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c
index f56dbe26d7c..68a4b8ca2de 100644
--- a/lib/libssl/s3_lib.c
+++ b/lib/libssl/s3_lib.c
@@ -2419,6 +2419,151 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
},
#endif /* OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_SRP
+ /* Cipher C01A */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aNULL,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 168,
+ 168,
+ },
+
+ /* Cipher C01B */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 168,
+ 168,
+ },
+
+ /* Cipher C01C */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 168,
+ 168,
+ },
+
+ /* Cipher C01D */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aNULL,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 128,
+ 128,
+ },
+
+ /* Cipher C01E */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 128,
+ 128,
+ },
+
+ /* Cipher C01F */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 128,
+ 128,
+ },
+
+ /* Cipher C020 */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aNULL,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 256,
+ 256,
+ },
+
+ /* Cipher C021 */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 256,
+ 256,
+ },
+
+ /* Cipher C022 */
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+ 256,
+ 256,
+ },
+#endif /* OPENSSL_NO_SRP */
#ifndef OPENSSL_NO_ECDH
/* HMAC based TLS v1.2 ciphersuites from RFC5289 */
@@ -2808,6 +2953,9 @@ ssl3_new(SSL *s)
s->s3 = s3;
+#ifndef OPENSSL_NO_SRP
+ SSL_SRP_CTX_init(s);
+#endif
s->method->ssl_clear(s);
return (1);
err:
@@ -2850,6 +2998,9 @@ ssl3_free(SSL *s)
}
if (s->s3->handshake_dgst)
ssl3_free_digest_list(s);
+#ifndef OPENSSL_NO_SRP
+ SSL_SRP_CTX_free(s);
+#endif
OPENSSL_cleanse(s->s3, sizeof *s->s3);
OPENSSL_free(s->s3);
s->s3 = NULL;
@@ -2934,6 +3085,13 @@ ssl3_clear(SSL *s)
#endif
}
+#ifndef OPENSSL_NO_SRP
+static char *
+srp_password_from_info_cb(SSL *s, void *arg)
+{
+ return BUF_strdup(s->srp_ctx.info);
+}
+#endif
long
ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
@@ -3375,6 +3533,36 @@ ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return 1;
break;
+#ifndef OPENSSL_NO_SRP
+ case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME:
+ ctx->srp_ctx.srp_Mask|=SSL_kSRP;
+ if (ctx->srp_ctx.login != NULL)
+ OPENSSL_free(ctx->srp_ctx.login);
+ ctx->srp_ctx.login = NULL;
+ if (parg == NULL)
+ break;
+ if (strlen((const char *)parg) > 255 || strlen((const char *)parg) < 1) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_SRP_USERNAME);
+ return 0;
+ }
+ if ((ctx->srp_ctx.login = BUF_strdup((char *)parg)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ break;
+ case SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD:
+ ctx->srp_ctx.SRP_give_srp_client_pwd_callback = srp_password_from_info_cb;
+ ctx->srp_ctx.info = parg;
+ break;
+ case SSL_CTRL_SET_SRP_ARG:
+ ctx->srp_ctx.srp_Mask|=SSL_kSRP;
+ ctx->srp_ctx.SRP_cb_arg = parg;
+ break;
+
+ case SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH:
+ ctx->srp_ctx.strength = larg;
+ break;
+#endif
#endif /* !OPENSSL_NO_TLSEXT */
/* A Thawte special :-) */
@@ -3452,6 +3640,23 @@ ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int))fp;
break;
+#ifndef OPENSSL_NO_SRP
+ case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB:
+ ctx->srp_ctx.srp_Mask|=SSL_kSRP;
+ ctx->srp_ctx.SRP_verify_param_callback =
+ (int (*)(SSL *, void *))fp;
+ break;
+ case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB:
+ ctx->srp_ctx.srp_Mask|=SSL_kSRP;
+ ctx->srp_ctx.TLS_ext_srp_username_callback =
+ (int (*)(SSL *, int *, void *))fp;
+ break;
+ case SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB:
+ ctx->srp_ctx.srp_Mask|=SSL_kSRP;
+ ctx->srp_ctx.SRP_give_srp_client_pwd_callback =
+ (char *(*)(SSL *, void *))fp;
+ break;
+#endif
#endif
default:
return (0);
@@ -3557,6 +3762,10 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
mask_a = cert->mask_a;
emask_k = cert->export_mask_k;
emask_a = cert->export_mask_a;
+#ifndef OPENSSL_NO_SRP
+ mask_k = cert->mask_k | s->srp_ctx.srp_Mask;
+ emask_k = cert->export_mask_k | s->srp_ctx.srp_Mask;
+#endif
#ifdef KSSL_DEBUG
/* printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
diff --git a/lib/libssl/s3_srvr.c b/lib/libssl/s3_srvr.c
index 1a924f828e5..cc46e241d4f 100644
--- a/lib/libssl/s3_srvr.c
+++ b/lib/libssl/s3_srvr.c
@@ -180,6 +180,28 @@ static const SSL_METHOD
return (NULL);
}
+#ifndef OPENSSL_NO_SRP
+static int
+ssl_check_srp_ext_ClientHello(SSL *s, int *al)
+{
+ int ret = SSL_ERROR_NONE;
+
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
+ (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
+ if (s->srp_ctx.login == NULL) {
+ /* RFC 5054 says SHOULD reject,
+ we do so if There is no srp login name */
+ ret = SSL3_AL_FATAL;
+ *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ } else {
+ ret = SSL_srp_server_param_with_username(s, al);
+ }
+ }
+ return ret;
+}
+#endif
IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
ssl3_accept, ssl_undefined_function, ssl3_get_server_method)
@@ -317,6 +339,39 @@ ssl3_accept(SSL *s)
if (ret <= 0)
goto end;
}
+#ifndef OPENSSL_NO_SRP
+ {
+ int al;
+ if ((ret =
+ ssl_check_srp_ext_ClientHello(s, &al))
+ < 0) {
+ /*
+ * Callback indicates further work to
+ * be done.
+ */
+ s->rwstate = SSL_X509_LOOKUP;
+ goto end;
+ }
+ if (ret != SSL_ERROR_NONE) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+
+ /*
+ * This is not really an error but the
+ * only means for a client to detect
+ * whether srp is supported.
+ */
+ if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
+ SSLerr(SSL_F_SSL3_ACCEPT,
+ SSL_R_CLIENTHELLO_TLSEXT);
+
+ ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ ret = -1;
+ goto end;
+
+ }
+ }
+#endif
s->renegotiate = 2;
s->state = SSL3_ST_SW_SRVR_HELLO_A;
@@ -415,6 +470,10 @@ ssl3_accept(SSL *s)
#ifndef OPENSSL_NO_PSK
|| ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
#endif
+#ifndef OPENSSL_NO_SRP
+ /* SRP: send ServerKeyExchange */
+ || (alg_k & SSL_kSRP)
+#endif
|| (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH))
|| (alg_k & SSL_kEECDH)
|| ((alg_k & SSL_kRSA)
@@ -1751,6 +1810,19 @@ ssl3_send_server_key_exchange(SSL *s)
n += 2 + pskhintlen;
} else
#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (type & SSL_kSRP) {
+ if ((s->srp_ctx.N == NULL) || (s->srp_ctx.g == NULL) ||
+ (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, SSL_R_MISSING_SRP_PARAM);
+ goto err;
+ }
+ r[0] = s->srp_ctx.N;
+ r[1] = s->srp_ctx.g;
+ r[2] = s->srp_ctx.s;
+ r[3] = s->srp_ctx.B;
+ } else
+#endif
{
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
@@ -1758,6 +1830,11 @@ ssl3_send_server_key_exchange(SSL *s)
}
for (i = 0; i < 4 && r[i] != NULL; i++) {
nr[i] = BN_num_bytes(r[i]);
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP))
+ n += 1 + nr[i];
+ else
+#endif
n += 2 + nr[i];
}
@@ -1783,6 +1860,12 @@ ssl3_send_server_key_exchange(SSL *s)
p = &(d[4]);
for (i = 0; i < 4 && r[i] != NULL; i++) {
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP)) {
+ *p = nr[i];
+ p++;
+ } else
+#endif
s2n(nr[i], p);
BN_bn2bin(r[i], p);
p += nr[i];
@@ -2651,6 +2734,43 @@ ssl3_get_client_key_exchange(SSL *s)
goto f_err;
} else
#endif
+#ifndef OPENSSL_NO_SRP
+ if (alg_k & SSL_kSRP) {
+ int param_len;
+
+ n2s(p, i);
+ param_len = i + 2;
+ if (param_len > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_BAD_SRP_A_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.A = BN_bin2bn(p, i, NULL))) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_BN_LIB);
+ goto err;
+ }
+ if (s->session->srp_username != NULL)
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((s->session->master_key_length =
+ SRP_generate_server_master_secret(s,
+ s->session->master_key)) < 0) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ p += i;
+ } else
+#endif /* OPENSSL_NO_SRP */
if (alg_k & SSL_kGOST) {
int ret = 0;
EVP_PKEY_CTX *pkey_ctx;
@@ -2731,7 +2851,9 @@ ssl3_get_client_key_exchange(SSL *s)
return (1);
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) || defined(OPENSSL_NO_SRP)
err:
+#endif
#ifndef OPENSSL_NO_ECDH
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
diff --git a/lib/libssl/ssl.h b/lib/libssl/ssl.h
index 3f99de16166..d3e015e738c 100644
--- a/lib/libssl/ssl.h
+++ b/lib/libssl/ssl.h
@@ -533,6 +533,9 @@ struct ssl_session_st {
size_t tlsext_ticklen; /* Session ticket length */
long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
#endif
+#ifndef OPENSSL_NO_SRP
+ char *srp_username;
+#endif
};
#endif
@@ -682,6 +685,42 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version,
#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+#ifndef OPENSSL_NO_SRP
+
+#ifndef OPENSSL_NO_SSL_INTERN
+
+typedef struct srp_ctx_st {
+ /* param for all the callbacks */
+ void *SRP_cb_arg;
+ /* set client Hello login callback */
+ int (*TLS_ext_srp_username_callback)(SSL *, int *, void *);
+ /* set SRP N/g param callback for verification */
+ int (*SRP_verify_param_callback)(SSL *, void *);
+ /* set SRP client passwd callback */
+ char *(*SRP_give_srp_client_pwd_callback)(SSL *, void *);
+
+ char *login;
+ BIGNUM *N, *g, *s, *B, *A;
+ BIGNUM *a, *b, *v;
+ char *info;
+ int strength;
+
+ unsigned long srp_Mask;
+} SRP_CTX;
+
+#endif
+
+/* see tls_srp.c */
+int SSL_SRP_CTX_init(SSL *s);
+int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
+int SSL_SRP_CTX_free(SSL *ctx);
+int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
+int SSL_srp_server_param_with_username(SSL *s, int *ad);
+int SRP_generate_server_master_secret(SSL *s, unsigned char *master_key);
+int SRP_Calc_A_param(SSL *s);
+int SRP_generate_client_master_secret(SSL *s, unsigned char *master_key);
+
+#endif
#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
@@ -903,6 +942,9 @@ struct ssl_ctx_st {
struct ssl3_buf_freelist_st *wbuf_freelist;
struct ssl3_buf_freelist_st *rbuf_freelist;
#endif
+#ifndef OPENSSL_NO_SRP
+ SRP_CTX srp_ctx; /* ctx for SRP authentication */
+#endif
#ifndef OPENSSL_NO_TLSEXT
@@ -1306,6 +1348,9 @@ struct ssl_st {
* 2 if we are a server and are inside a handshake
* (i.e. not just sending a HelloRequest) */
+#ifndef OPENSSL_NO_SRP
+ SRP_CTX srp_ctx; /* ctx for SRP authentication */
+#endif
};
#endif
@@ -1754,6 +1799,24 @@ int SSL_set_trust(SSL *s, int trust);
int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
+#ifndef OPENSSL_NO_SRP
+int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
+int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
+int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
+int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, char *(*cb)(SSL *, void *));
+int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, int (*cb)(SSL *, void *));
+int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, int (*cb)(SSL *, int *, void *));
+int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
+
+int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g, BIGNUM *sa, BIGNUM *v, char *info);
+int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, const char *grp);
+
+BIGNUM *SSL_get_srp_g(SSL *s);
+BIGNUM *SSL_get_srp_N(SSL *s);
+
+char *SSL_get_srp_username(SSL *s);
+char *SSL_get_srp_userinfo(SSL *s);
+#endif
void SSL_free(SSL *ssl);
int SSL_accept(SSL *ssl);
diff --git a/lib/libssl/ssl_asn1.c b/lib/libssl/ssl_asn1.c
index b1a3876c91a..28e295f6a44 100644
--- a/lib/libssl/ssl_asn1.c
+++ b/lib/libssl/ssl_asn1.c
@@ -113,6 +113,9 @@ typedef struct ssl_session_asn1_st {
ASN1_OCTET_STRING psk_identity_hint;
ASN1_OCTET_STRING psk_identity;
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ ASN1_OCTET_STRING srp_username;
+#endif /* OPENSSL_NO_SRP */
} SSL_SESSION_ASN1;
int
@@ -130,6 +133,9 @@ i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
unsigned char cbuf;
int v11 = 0;
#endif
+#ifndef OPENSSL_NO_SRP
+ int v12 = 0;
+#endif
long l;
SSL_SESSION_ASN1 a;
M_ASN1_I2D_vars(in);
@@ -247,6 +253,13 @@ i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
a.psk_identity.data = (unsigned char *)(in->psk_identity);
}
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (in->srp_username) {
+ a.srp_username.length = strlen(in->srp_username);
+ a.srp_username.type = V_ASN1_OCTET_STRING;
+ a.srp_username.data = (unsigned char *)(in->srp_username);
+ }
+#endif /* OPENSSL_NO_SRP */
M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
@@ -287,6 +300,10 @@ i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
if (in->psk_identity)
M_ASN1_I2D_len_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING, 8, v8);
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (in->srp_username)
+ M_ASN1_I2D_len_EXP_opt(&(a.srp_username), i2d_ASN1_OCTET_STRING, 12, v12);
+#endif /* OPENSSL_NO_SRP */
M_ASN1_I2D_seq_total();
@@ -331,6 +348,10 @@ i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
if (in->compress_meth)
M_ASN1_I2D_put_EXP_opt(&(a.comp_id), i2d_ASN1_OCTET_STRING, 11, v11);
#endif
+#ifndef OPENSSL_NO_SRP
+ if (in->srp_username)
+ M_ASN1_I2D_put_EXP_opt(&(a.srp_username), i2d_ASN1_OCTET_STRING, 12, v12);
+#endif /* OPENSSL_NO_SRP */
M_ASN1_I2D_finish();
}
@@ -559,6 +580,18 @@ long length)
}
#endif
+#ifndef OPENSSL_NO_SRP
+ os.length = 0;
+ os.data = NULL;
+ M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 12);
+ if (os.data) {
+ ret->srp_username = BUF_strndup((char *)os.data, os.length);
+ OPENSSL_free(os.data);
+ os.data = NULL;
+ os.length = 0;
+ } else
+ ret->srp_username = NULL;
+#endif /* OPENSSL_NO_SRP */
M_ASN1_D2I_Finish(a, SSL_SESSION_free, SSL_F_D2I_SSL_SESSION);
}
diff --git a/lib/libssl/ssl_ciph.c b/lib/libssl/ssl_ciph.c
index 1a87cc255d8..4bd3be0d41f 100644
--- a/lib/libssl/ssl_ciph.c
+++ b/lib/libssl/ssl_ciph.c
@@ -724,7 +724,9 @@ ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long
*mkey |= SSL_kPSK;
*auth |= SSL_aPSK;
#endif
+#ifdef OPENSSL_NO_SRP
*mkey |= SSL_kSRP;
+#endif
/* Check for presence of GOST 34.10 algorithms, and if they
* do not present, disable appropriate auth and key exchange */
if (!get_optional_pkey_id("gost94")) {
diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c
index d0c79710ef1..a0882e45215 100644
--- a/lib/libssl/ssl_lib.c
+++ b/lib/libssl/ssl_lib.c
@@ -1823,6 +1823,9 @@ SSL_CTX
ret->psk_client_callback = NULL;
ret->psk_server_callback = NULL;
#endif
+#ifndef OPENSSL_NO_SRP
+ SSL_CTX_SRP_CTX_init(ret);
+#endif
#ifndef OPENSSL_NO_BUF_FREELISTS
ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
@@ -1962,6 +1965,9 @@ SSL_CTX_free(SSL_CTX *a)
if (a->psk_identity_hint)
OPENSSL_free(a->psk_identity_hint);
#endif
+#ifndef OPENSSL_NO_SRP
+ SSL_CTX_SRP_CTX_free(a);
+#endif
#ifndef OPENSSL_NO_ENGINE
if (a->client_cert_engine)
ENGINE_finish(a->client_cert_engine);
diff --git a/lib/libssl/ssl_sess.c b/lib/libssl/ssl_sess.c
index 5c5ef4a312c..0b1c655820d 100644
--- a/lib/libssl/ssl_sess.c
+++ b/lib/libssl/ssl_sess.c
@@ -224,6 +224,9 @@ SSL_SESSION
ss->psk_identity_hint = NULL;
ss->psk_identity = NULL;
#endif
+#ifndef OPENSSL_NO_SRP
+ ss->srp_username = NULL;
+#endif
return (ss);
}
@@ -734,6 +737,10 @@ SSL_SESSION_free(SSL_SESSION *ss)
if (ss->psk_identity != NULL)
OPENSSL_free(ss->psk_identity);
#endif
+#ifndef OPENSSL_NO_SRP
+ if (ss->srp_username != NULL)
+ OPENSSL_free(ss->srp_username);
+#endif
OPENSSL_cleanse(ss, sizeof(*ss));
OPENSSL_free(ss);
}
diff --git a/lib/libssl/ssl_txt.c b/lib/libssl/ssl_txt.c
index d3f304b73d9..91664ffe432 100644
--- a/lib/libssl/ssl_txt.c
+++ b/lib/libssl/ssl_txt.c
@@ -193,6 +193,12 @@ SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
if (BIO_printf(bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None")
<= 0) goto err;
#endif
+#ifndef OPENSSL_NO_SRP
+ if (BIO_puts(bp, "\n SRP username: ")
+ <= 0) goto err;
+ if (BIO_printf(bp, "%s", x->srp_username ? x->srp_username : "None")
+ <= 0) goto err;
+#endif
#ifndef OPENSSL_NO_TLSEXT
if (x->tlsext_tick_lifetime_hint) {
if (BIO_printf(bp,
diff --git a/lib/libssl/t1_lib.c b/lib/libssl/t1_lib.c
index c4eeb7a41d2..c3d62957ae3 100644
--- a/lib/libssl/t1_lib.c
+++ b/lib/libssl/t1_lib.c
@@ -427,6 +427,35 @@ unsigned char
ret += el;
}
+#ifndef OPENSSL_NO_SRP
+ /* Add SRP username if there is one */
+ if (s->srp_ctx.login != NULL)
+ { /* Add TLS extension SRP username to the Client Hello message */
+
+ int login_len = strlen(s->srp_ctx.login);
+
+ if (login_len > 255 || login_len == 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /* check for enough space.
+ 4 for the srp type type and entension length
+ 1 for the srp user identity
+ + srp user identity length
+ */
+ if ((limit - ret - 5 - login_len)
+ < 0) return NULL;
+
+
+ /* fill in the extension */
+ s2n(TLSEXT_TYPE_srp, ret);
+ s2n(login_len + 1, ret);
+ (*ret++) = (unsigned char) login_len;
+ memcpy(ret, s->srp_ctx.login, login_len);
+ ret += login_len;
+ }
+#endif
#ifndef OPENSSL_NO_EC
if (s->tlsext_ecpointformatlist != NULL &&
@@ -1042,6 +1071,27 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
}
}
+#ifndef OPENSSL_NO_SRP
+ else if (type == TLSEXT_TYPE_srp) {
+ if (size <= 0 || ((len = data[0])) != (size - 1)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (s->srp_ctx.login != NULL) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ if ((s->srp_ctx.login = OPENSSL_malloc(len + 1)) == NULL)
+ return -1;
+ memcpy(s->srp_ctx.login, &data[1], len);
+ s->srp_ctx.login[len] = '\0';
+
+ if (strlen(s->srp_ctx.login) != len) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ }
+#endif
#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats &&