Whamcloud - gitweb
LU-8602 gss: support OpenSSL 1.1
[fs/lustre-release.git] / lustre / utils / gss / lgss_sk_utils.c
index 39cd25d..b6f1fd8 100644 (file)
@@ -88,35 +88,38 @@ static void lgss_sk_release_cred(struct lgss_cred *cred)
 static int lgss_sk_using_cred(struct lgss_cred *cred)
 {
        struct sk_cred *skc = cred->lc_mech_cred;
-       gss_buffer_desc bufs[7];
+       gss_buffer_desc bufs[SK_INIT_BUFFERS];
+       uint32_t version;
        uint32_t flags;
-       int numbufs = 7;
        int rc;
 
-       rc = sk_gen_params(skc, true);
+       rc = sk_gen_params(skc);
        if (rc)
                return rc;
 
        /* HMAC is generated in this order */
-       bufs[0] = skc->sc_kctx.skc_iv;
-       bufs[1] = skc->sc_p;
-       bufs[2] = skc->sc_pub_key;
-       bufs[3] = skc->sc_tgt;
-       bufs[4] = skc->sc_nodemap_hash;
-
-       /* big endian flags for the wire */
-       flags = htobe64(skc->sc_flags);
-       bufs[5].value = &flags;
-       bufs[5].length = sizeof(flags);
+       version = htobe32(SK_MSG_VERSION);
+       bufs[SK_INIT_VERSION].value = &version;
+       bufs[SK_INIT_VERSION].length = sizeof(version);
+       bufs[SK_INIT_RANDOM].value = &skc->sc_kctx.skc_host_random;
+       bufs[SK_INIT_RANDOM].length = sizeof(skc->sc_kctx.skc_host_random);
+       bufs[SK_INIT_PUB_KEY] = skc->sc_pub_key;
+       bufs[SK_INIT_P] = skc->sc_p;
+       bufs[SK_INIT_TARGET] = skc->sc_tgt;
+       bufs[SK_INIT_NODEMAP] = skc->sc_nodemap_hash;
+       flags = htobe32(skc->sc_flags);
+       bufs[SK_INIT_FLAGS].value = &flags;
+       bufs[SK_INIT_FLAGS].length = sizeof(flags);
 
        /* sign all the bufs except HMAC */
-       rc = sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs, numbufs - 1,
-                         EVP_sha256(), &skc->sc_hmac);
+       rc = sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs,
+                         SK_INIT_BUFFERS - 1, EVP_sha256(),
+                         &skc->sc_hmac);
        if (rc)
                return rc;
 
-       bufs[6] = skc->sc_hmac;
-       rc = sk_encode_netstring(bufs, numbufs, &cred->lc_mech_token);
+       bufs[SK_INIT_HMAC] = skc->sc_hmac;
+       rc = sk_encode_netstring(bufs, SK_INIT_BUFFERS, &cred->lc_mech_token);
        if (rc)
                return rc;
 
@@ -130,27 +133,50 @@ static int lgss_sk_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
                                 gss_buffer_desc *ctx_token)
 {
        struct sk_cred *skc = cred->lc_mech_cred;
-       gss_buffer_desc bufs[2];
-       int numbufs = 2;
+       gss_buffer_desc bufs[SK_RESP_BUFFERS];
+       uint32_t version;
        int i;
        uint32_t rc;
 
-       i = sk_decode_netstring(bufs, numbufs, token);
-       if (i < numbufs) {
-               printerr(0, "Failed to decode netstring\n");
-               return -1;
+       /* Decode responder buffers and validate */
+       i = sk_decode_netstring(bufs, SK_RESP_BUFFERS, token);
+       if (i != SK_RESP_BUFFERS) {
+               printerr(0, "Invalid token received\n");
+               return -EINVAL;
        }
 
-       /* decoded buffers from server should be:
-        * bufs[0] = sc_pub_key
-        * bufs[1] = sc_hmac */
-       rc = sk_verify_hmac(skc, bufs, numbufs - 1, EVP_sha256(), &bufs[1]);
+       rc = sk_verify_hmac(skc, bufs, SK_RESP_BUFFERS - 1, EVP_sha256(),
+                           &bufs[SK_RESP_HMAC]);
        if (rc != GSS_S_COMPLETE) {
                printerr(0, "Invalid HMAC receieved: 0x%x\n", rc);
-               return -1;
+               return -EINVAL;
+       }
+
+       if (bufs[SK_RESP_VERSION].length != sizeof(version)) {
+               printerr(0, "Invalid version received (wrong size)\n");
+               return -EINVAL;
+       }
+       memcpy(&version, bufs[SK_RESP_VERSION].value, sizeof(version));
+       version = be32toh(version);
+       if (version != SK_MSG_VERSION) {
+               printerr(0, "Invalid version received: %d\n", version);
+               return -EINVAL;
+       }
+
+       /* In the rare event that both the random values are equal the
+        * client has the responsability to retry the connection attempt
+        * otherwise we would leak information about the plain text by
+        * reuusing IVs as both peer and host use the same values other
+        * than the nonce. */
+       memcpy(&skc->sc_kctx.skc_peer_random, bufs[SK_RESP_RANDOM].value,
+              sizeof(skc->sc_kctx.skc_peer_random));
+       if (skc->sc_kctx.skc_host_random == skc->sc_kctx.skc_peer_random) {
+               printerr(0, "Host and peer randoms are equal, must retry to "
+                        "ensure unique value for nonce\n");
+               return -EAGAIN;
        }
 
-       rc = sk_compute_key(skc, &bufs[0]);
+       rc = sk_compute_dh_key(skc, &bufs[SK_RESP_PUB_KEY]);
        if (rc == GSS_S_DEFECTIVE_TOKEN) {
                /* Defective token for short key means we need to retry
                 * because there is a chance that the parameters generated
@@ -159,18 +185,25 @@ static int lgss_sk_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
                return -EAGAIN;
        } else if (rc != GSS_S_COMPLETE) {
                printerr(0, "Failed to compute session key: 0x%x\n", rc);
-               return -1;
+               return -EINVAL;
        }
 
-       rc = sk_kdf(skc, cred->lc_self_nid, &cred->lc_mech_token);
+       rc = sk_session_kdf(skc, cred->lc_self_nid, &cred->lc_mech_token,
+                           token);
        if (rc) {
                printerr(0, "Failed to calulate derived key\n");
-               return -1;
+               return -EINVAL;
+       }
+
+       rc = sk_compute_keys(skc);
+       if (rc) {
+               printerr(0, "Failed to compute HMAC and session key\n");
+               return -EINVAL;
        }
 
        if (sk_serialize_kctx(skc, ctx_token)) {
                printerr(0, "Failed to serialize context for kernel\n");
-               return -1;
+               return -EINVAL;
        }
 
        return 0;