From 495a1e5c3aec4d44558cd86161b8385f1b1b6822 Mon Sep 17 00:00:00 2001 From: Antoine Salon Date: Thu, 25 Oct 2018 15:43:35 -0700 Subject: [PATCH] SRP module documentation Signed-off-by: Antoine Salon Reviewed-by: Paul Dale Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/7522) --- crypto/srp/srp_lib.c | 8 +- crypto/srp/srp_vfy.c | 15 +- doc/man1/srp.pod | 2 +- doc/man3/SRP_VBASE_new.pod | 91 +++++++++ doc/man3/SRP_create_verifier.pod | 115 ++++++++++++ doc/man3/SSL_CTX_add_extra_chain_cert.pod | 2 + doc/man3/SSL_CTX_set_srp_password.pod | 216 ++++++++++++++++++++++ doc/man7/ssl.pod | 27 +++ 8 files changed, 466 insertions(+), 10 deletions(-) create mode 100644 doc/man3/SRP_VBASE_new.pod create mode 100644 doc/man3/SRP_create_verifier.pod create mode 100644 doc/man3/SSL_CTX_set_srp_password.pod diff --git a/crypto/srp/srp_lib.c b/crypto/srp/srp_lib.c index b97d630d37..a9e244ea91 100644 --- a/crypto/srp/srp_lib.c +++ b/crypto/srp/srp_lib.c @@ -44,13 +44,13 @@ static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N) static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g) { - /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */ + /* k = SHA1(N | PAD(g)) -- tls-srp RFC 5054 */ return srp_Calc_xy(N, g, N); } BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N) { - /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ + /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */ return srp_Calc_xy(A, B, N); } @@ -254,13 +254,13 @@ static SRP_gN knowngN[] = { /* * Check if G and N are known parameters. The values have been generated - * from the ietf-tls-srp draft version 8 + * from the IETF RFC 5054 */ char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N) { size_t i; if ((g == NULL) || (N == NULL)) - return 0; + return NULL; for (i = 0; i < KNOWN_GN_NUMBER; i++) { if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index 17b35c00f9..622fffbcd0 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -340,12 +340,13 @@ static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab) int i; SRP_gN *gN; - if (gN_tab != NULL) + if (gN_tab != NULL) { for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) { gN = sk_SRP_gN_value(gN_tab, i); if (gN && (id == NULL || strcmp(gN->id, id) == 0)) return gN; } + } return SRP_get_default_gN(id); } @@ -374,9 +375,13 @@ static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) } /* - * this function parses verifier file. Format is: - * string(index):base64(N):base64(g):0 - * string(username):base64(v):base64(salt):int(index) + * This function parses the verifier file generated by the srp app. + * The format for each entry is: + * V base64(verifier) base64(salt) username gNid userinfo(optional) + * or + * I base64(N) base64(g) + * Note that base64 is the SRP variant of base64 encoding described + * in t_fromb64(). */ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) @@ -605,7 +610,7 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, g_bn = g_bn_alloc; defgNid = "*"; } else { - SRP_gN *gN = SRP_get_gN_by_id(g, NULL); + SRP_gN *gN = SRP_get_default_gN(g); if (gN == NULL) goto err; N_bn = gN->N; diff --git a/doc/man1/srp.pod b/doc/man1/srp.pod index e858a22260..4977431029 100644 --- a/doc/man1/srp.pod +++ b/doc/man1/srp.pod @@ -25,7 +25,7 @@ B =head1 DESCRIPTION -The B command is user to maintain an SRP (secure remote password) +The B command is used to maintain an SRP (secure remote password) file. At most one of the B<-add>, B<-modify>, B<-delete>, and B<-list> options can be specified. diff --git a/doc/man3/SRP_VBASE_new.pod b/doc/man3/SRP_VBASE_new.pod new file mode 100644 index 0000000000..b235e58710 --- /dev/null +++ b/doc/man3/SRP_VBASE_new.pod @@ -0,0 +1,91 @@ +=pod + +=head1 NAME + +SRP_VBASE_new, +SRP_VBASE_free, +SRP_user_pwd_free, +SRP_VBASE_init, +SRP_VBASE_get1_by_user, +SRP_VBASE_get_by_user +- Functions to create and manage a stack of SRP user verifier information + +=head1 SYNOPSIS + + #include + + SRP_VBASE *SRP_VBASE_new(char *seed_key); + void SRP_VBASE_free(SRP_VBASE *vb); + void SRP_user_pwd_free(SRP_user_pwd *user_pwd); + + int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file); + + SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username); + SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username); + +=head1 DESCRIPTION + +The SRP_VBASE_new() function allocates a structure to store server side SRP +verifier information. If B is not NULL a copy is stored and used to +generate dummy parameters for users that are not found by SRP_VBASE_get1_by_user(). +This allows the server to hide the fact that it doesn't have a verifier for a +particular username, as described in section 2.5.1.3 'Unknown SRP' of RFC 5054. +The seed string should contain random NUL terminated binary data (therefore +the random data should not contain NUL bytes!). + +The SRP_VBASE_free() function frees up the B structure. +If B is NULL, nothing is done. + +The SRP_user_pwd_free() function frees up the B structure. +If B is NULL, nothing is done. + +The SRP_VBASE_init() function parses the information in a verifier file and +populates the B structure. +The verifier file is a text file containing multiple entries, whose format is: +flag base64(verifier) base64(salt) username gNid userinfo(optional) +where the flag can be 'V' (valid) or 'R' (revoked). +Note that the base64 encoding used here is non-standard so it is recommended +to use L to generate this file. + +The SRP_VBASE_get1_by_user() function returns the password info for the user +whose username matches B. It replaces the deprecated +SRP_VBASE_get_by_user(). +If no matching user is found but a seed_key and default gN parameters have been +set, dummy authentication information is generated from the seed_key, allowing +the server to hide the fact that it doesn't have a verifier for a particular +username. When using SRP as a TLS authentication mechanism, this will cause +the handshake to proceed normally but the first client will be rejected with +a "bad_record_mac" alert, as if the password was incorrect. +If no matching user is found and the seed_key is not set, NULL is returned. +Ownership of the returned pointer is released to the caller, it must be freed +with SRP_user_pwd_free(). + +=head1 RETURN VALUES + +SRP_VBASE_init() returns B (0) on success and a positive value +on failure. +The error codes are B if the file could not be opened, +B if the file could not be parsed, +B on memory allocation failure and B +for invalid decoded parameter values. + +=head1 SEE ALSO + +L, +L, +L + +=head1 HISTORY + +These functions were first added to OpenSSL 1.0.1. + +=head1 COPYRIGHT + +Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/SRP_create_verifier.pod b/doc/man3/SRP_create_verifier.pod new file mode 100644 index 0000000000..9741c5c47c --- /dev/null +++ b/doc/man3/SRP_create_verifier.pod @@ -0,0 +1,115 @@ +=pod + +=head1 NAME + +SRP_create_verifier, +SRP_create_verifier_BN, +SRP_check_known_gN_param, +SRP_get_default_gN +- SRP authentication primitives + +=head1 SYNOPSIS + + #include + + char *SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, const BIGNUM *g); + char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g); + + char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N); + SRP_gN *SRP_get_default_gN(const char *id); + +=head1 DESCRIPTION + +The SRP_create_verifier_BN() function creates an SRP password verifier from +the supplied parameters as defined in section 2.4 of RFC 5054. +On successful exit B<*verifier> will point to a newly allocated BIGNUM containing +the verifier and (if a salt was not provided) B<*salt> will be populated with a +newly allocated BIGNUM containing a random salt. If B<*salt> is not NULL then +the provided salt is used instead. +The caller is responsible for freeing the allocated B<*salt> and B<*verifier> +BIGNUMS (use L). + +The SRP_create_verifier() function is similar to SRP_create_verifier_BN() but +all numeric parameters are in a non-standard base64 encoding originally designed +for compatibility with libsrp. This is mainly present for historical compatibility +and its use is discouraged. +It is possible to pass NULL as B and an SRP group id as B instead to +load the appropriate gN values (see SRP_get_default_gN()). +If both B and B are NULL the 8192-bit SRP group parameters are used. +The caller is responsible for freeing the allocated *salt and *verifier char* +(use L). + +The SRP_check_known_gN_param() function checks that B and B are valid +SRP group parameters from RFC 5054 appendix A. + +The SRP_get_default_gN() function returns the gN parameters for the RFC 5054 B +SRP group size. +The known ids are "1024", "1536", "2048", "3072", "4096", "6144" and "8192". + +=head1 RETURN VALUES + +SRP_create_verifier_BN() returns 1 on success and 0 on failure. + +SRP_create_verifier() returns NULL on failure and a non-NULL value on success: +"*" if B is not NULL, the selected group id otherwise. This value should +not be freed. + +SRP_check_known_gN_param() returns the text representation of the group id +(ie. the prime bit size) or NULL if the arguments are not valid SRP group parameters. +This value should not be freed. + +SRP_get_default_gN() returns NULL if B is not a valid group size, +or the 8192-bit group parameters if B is NULL. + +=head1 EXAMPLES + +Generate and store a 8192 bit password verifier (error handling +omitted for clarity): + + #include + #include + + const char *username = "username"; + const char *password = "password"; + + SRP_VBASE *srpData = SRP_VBASE_new(NULL); + + SRP_user_pwd *pwd = (SRP_user_pwd*) OPENSSL_malloc(sizeof(SRP_user_pwd)); + SRP_gN *gN = SRP_get_default_gN("8192"); + + BIGNUM *salt = NULL, *verifier = NULL; + SRP_create_verifier_BN(username, password, &salt, &verifier, gN->N, gN->g); + + // TODO: replace with SRP_user_pwd_new() + pwd->id = OPENSSL_strdup(username); + pwd->g = gN->g; + pwd->N = gN->N; + pwd->s = salt; + pwd->v = verifier; + pwd->info = NULL; + + sk_SRP_user_pwd_push(srpData->users_pwd, pwd); + +=head1 SEE ALSO + +L, +L, +L, +L + +=head1 HISTORY + +These functions were first added to OpenSSL 1.0.1. + +=head1 COPYRIGHT + +Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/SSL_CTX_add_extra_chain_cert.pod b/doc/man3/SSL_CTX_add_extra_chain_cert.pod index 6e429c31bd..b8f11b3a2d 100644 --- a/doc/man3/SSL_CTX_add_extra_chain_cert.pod +++ b/doc/man3/SSL_CTX_add_extra_chain_cert.pod @@ -26,9 +26,11 @@ after another. SSL_CTX_get_extra_chain_certs() retrieves the extra chain certificates associated with B, or the chain associated with the current certificate of B if the extra chain is empty. +The returned stack should not be freed by the caller. SSL_CTX_get_extra_chain_certs_only() retrieves the extra chain certificates associated with B. +The returned stack should not be freed by the caller. SSL_CTX_clear_extra_chain_certs() clears all extra chain certificates associated with B. diff --git a/doc/man3/SSL_CTX_set_srp_password.pod b/doc/man3/SSL_CTX_set_srp_password.pod new file mode 100644 index 0000000000..6f33230aaa --- /dev/null +++ b/doc/man3/SSL_CTX_set_srp_password.pod @@ -0,0 +1,216 @@ +=pod + +=head1 NAME + +SSL_CTX_set_srp_username, +SSL_CTX_set_srp_password, +SSL_CTX_set_srp_strength, +SSL_CTX_set_srp_cb_arg, +SSL_CTX_set_srp_username_callback, +SSL_CTX_set_srp_client_pwd_callback, +SSL_CTX_set_srp_verify_param_callback, +SSL_set_srp_server_param, +SSL_set_srp_server_param_pw, +SSL_get_srp_g, +SSL_get_srp_N, +SSL_get_srp_username, +SSL_get_srp_userinfo +- SRP control operations + +=head1 SYNOPSIS + + #include + + 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_cb_arg(SSL_CTX *ctx, void *arg); + int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, + int (*cb) (SSL *s, int *ad, void *arg)); + int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, + char *(*cb) (SSL *s, void *arg)); + int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, + int (*cb) (SSL *s, 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); + +=head1 DESCRIPTION + +These functions provide access to SRP (Secure Remote Password) parameters, +an alternate authentication mechanism for TLS. SRP allows the use of user names +and passwords over unencrypted channels without revealing the password to an +eavesdropper. SRP also supplies a shared secret at the end of the authentication +sequence that can be used to generate encryption keys. + +The SRP protocol, version 3 is specified in RFC 2945. SRP version 6 is described +in RFC 5054 with applications to TLS authentication. + +The SSL_CTX_set_srp_username() function sets the SRP username for B. This +should be called on the client prior to creating a connection to the server. +The length of B must be shorter or equal to 255 characters. + +The SSL_CTX_set_srp_password() function sets the SRP password for B. This +may be called on the client prior to creating a connection to the server. +This overrides the effect of SSL_CTX_set_srp_client_pwd_callback(). + +The SSL_CTX_set_srp_strength() function sets the SRP strength for B. This +is the minimal length of the SRP prime in bits. If not specified 1024 is used. +If not satisfied by the server key exchange the connection will be rejected. + +The SSL_CTX_set_srp_cb_arg() function sets an extra parameter that will +be passed to all following callbacks as B. + +The SSL_CTX_set_srp_username_callback() function sets the server side callback +that is invoked when an SRP username is found in a ClientHello. +The callback parameters are the SSL connection B, a writable error flag B +and the extra argument B set by SSL_CTX_set_srp_cb_arg(). +This callback should setup the server for the key exchange by calling +SSL_set_srp_server_param() with the appropriate parameters for the received +username. The username can be obtained by calling SSL_get_srp_username(). +See L to parse the verifier file created by L or +L to generate it. +The callback should return B to proceed with the server key exchange, +B for a fatal error or any value < 0 for a retryable error. +In the event of a B the alert flag given by B<*al> will be sent +back. By default this will be B. + +The SSL_CTX_set_srp_client_pwd_callback() function sets the client password +callback on the client. +The callback parameters are the SSL connection B and the extra argument B +set by SSL_CTX_set_srp_cb_arg(). +The callback will be called as part of the generation of the client secrets. +It should return the client password in text form or NULL to abort the connection. +The resulting memory will be freed by the library as part of the callback resolution. +This overrides the effect of SSL_CTX_set_srp_password(). + +The SSL_CTX_set_srp_verify_param_callback() sets the SRP gN parameter verification +callback on the client. This allows the client to perform custom verification when +receiving the server SRP proposed parameters. +The callback parameters are the SSL connection B and the extra argument B +set by SSL_CTX_set_srp_cb_arg(). +The callback should return a positive value to accept the server parameters. +Returning 0 or a negative value will abort the connection. The server parameters +can be obtained by calling SSL_get_srp_N() and SSL_get_srp_g(). +Sanity checks are already performed by the library after the handshake +(B % N non zero, check against the strength parameter) and are not necessary. +If no callback is set the g and N parameters will be checked against +known RFC 5054 values. + +The SSL_set_srp_server_param() function sets all SRP parameters for +the connection B. B and B are the SRP group parameters, B is the +user salt, B the password verifier and B is the optional user info. + +The SSL_set_srp_server_param_pw() function sets all SRP parameters for the +connection B by generating a random salt and a password verifier. +B is the username, B the password and B the SRP group paramters +identifier for L. + +The SSL_get_srp_g() function returns the SRP group generator for B, or from +the underlying SSL_CTX if it is NULL. + +The SSL_get_srp_N() function returns the SRP prime for B, or from +the underlying SSL_CTX if it is NULL. + +The SSL_get_srp_username() function returns the SRP username for B, or from +the underlying SSL_CTX if it is NULL. + +The SSL_get_srp_userinfo() function returns the SRP user info for B, or from +the underlying SSL_CTX if it is NULL. + +=head1 RETURN VALUES + +All SSL_CTX_set_* functions return 1 on success and 0 on failure. + +SSL_set_srp_server_param() returns 1 on success and -1 on failure. + +The SSL_get_SRP_* functions return a pointer to the requested data, the memory +is owned by the library and should not be freed by the caller. + +=head1 EXAMPLES + +Setup SRP parameters on the client: + + #include + + const char *username = "username"; + const char *password = "password"; + + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + if (!ctx) + /* Error */ + if (!SSL_CTX_set_srp_username(ctx, username)) + /* Error */ + if (!SSL_CTX_set_srp_password(ctx, password)) + /* Error */ + +Setup SRP server with verifier file: + + #include + #include + + const char *srpvfile = "password.srpv"; + + int srpServerCallback(SSL *s, int *ad, void *arg) + { + SRP_VBASE *srpData = (SRP_VBASE*) arg; + char *username = SSL_get_srp_username(s); + + SRP_user_pwd *user_pwd = SRP_VBASE_get1_by_user(srpData, username); + if (!user_pwd) + /* Error */ + return SSL3_AL_FATAL; + + if (SSL_set_srp_server_param(s, user_pwd->N, user_pwd->g, + user_pwd->s, user_pwd->v, user_pwd->info) < 0) + /* Error */ + + SRP_user_pwd_free(user_pwd); + return SSL_ERROR_NONE; + } + + SSL_CTX *ctx = SSL_CTX_new(TLS_server_method()); + if (!ctx) + /* Error */ + + /* + * seedKey should contain a NUL terminated sequence + * of random non NUL bytes + */ + const char *seedKey; + + SRP_VBASE *srpData = SRP_VBASE_new(seedKey); + if (SRP_VBASE_init(srpData, (char*) srpvfile) != SRP_NO_ERROR) + /* Error */ + + SSL_CTX_set_srp_cb_arg(ctx, srpData); + SSL_CTX_set_srp_username_callback(ctx, srpServerCallback); + +=head1 SEE ALSO + +L, +L, +L + +=head1 HISTORY + +These functions were first added to OpenSSL 1.0.1. + +=head1 COPYRIGHT + +Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/ssl.pod b/doc/man7/ssl.pod index 1695f7ea19..60b1834f98 100644 --- a/doc/man7/ssl.pod +++ b/doc/man7/ssl.pod @@ -375,6 +375,20 @@ Use the file path to locate trusted CA certificates. =item void B(SSL_CTX *ctx, int mode); +=item int B(SSL_CTX *ctx, void *arg); + +=item int B(SSL_CTX *ctx, char *(*cb)(SSL *ssl, void *arg)); + +=item int B(SSL_CTX *ctx, char *password); + +=item int B(SSL_CTX *ctx, int strength); + +=item int B(SSL_CTX *ctx, char *name); + +=item int B(SSL_CTX *ctx, int (*cb)(SSL *ssl, int *ad, void *arg)); + +=item int B(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg)); + =item int B(SSL_CTX *ctx, const SSL_METHOD *meth); =item void B(SSL_CTX *ctx, long t); @@ -582,6 +596,14 @@ fresh handle for each connection. =item int B(const SSL *ssl); +=item BIGNUM *B(SSL *ssl); + +=item BIGNUM *B(SSL *ssl); + +=item char *B(SSL *ssl); + +=item char *B(SSL *ssl); + =item const SSL_METHOD *B(SSL *ssl); =item int B(const SSL *ssl); @@ -674,6 +696,10 @@ fresh handle for each connection. =item void B(SSL *ssl, int mode); +=item int B(SSL *ssl, const BIGNUM *N, const BIGNUM *g, BIGNUM *sa, BIGNUM *v, char *info); + +=item int B(SSL *ssl, const char *user, const char *pass, const char *grp); + =item int B(SSL *ssl, const SSL_METHOD *meth); =item void B(SSL *ssl, long t); @@ -790,6 +816,7 @@ L, L, L, L, +L, L, L, L,