4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (C) 2015, Trustees of Indiana University
25 * Author: Jeremy Filizetti <jfilizet@iu.edu>
30 #include <openssl/dh.h>
31 #include <openssl/engine.h>
32 #include <openssl/err.h>
35 #include "lgss_utils.h"
38 * Create the initial shared key credentials
40 static int lgss_sk_prepare_cred(struct lgss_cred *cred)
42 uint32_t flags = cred->lc_root_flags;
44 switch (cred->lc_svc_type) {
46 flags |= LGSS_SVC_NULL;
49 flags |= LGSS_SVC_AUTH;
52 flags |= LGSS_SVC_INTG;
55 flags |= LGSS_SVC_PRIV;
61 cred->lc_mech_cred = sk_create_cred(cred->lc_tgt_uuid, NULL, flags);
62 if (cred->lc_mech_cred == NULL) {
63 printerr(0, "sk: cannot create credential: %s\n",
71 /* Free all the sk_cred resources */
72 static void lgss_sk_release_cred(struct lgss_cred *cred)
74 struct sk_cred *skc = cred->lc_mech_cred;
77 cred->lc_mech_cred = NULL;
78 free(cred->lc_mech_token.value);
83 * Session key parameter generation is deferred until here because if privacy
84 * mode is enabled the session key parameter generation can take a while
85 * depending on the key size used and prepare is called before returning
86 * from the request_key upcall by lgss_keyring
88 static int lgss_sk_using_cred(struct lgss_cred *cred)
90 struct sk_cred *skc = cred->lc_mech_cred;
91 gss_buffer_desc bufs[7];
96 rc = sk_gen_params(skc, true);
100 /* HMAC is generated in this order */
101 bufs[0] = skc->sc_kctx.skc_iv;
103 bufs[2] = skc->sc_pub_key;
104 bufs[3] = skc->sc_tgt;
105 bufs[4] = skc->sc_nodemap_hash;
107 /* big endian flags for the wire */
108 flags = cpu_to_be32(skc->sc_flags);
109 bufs[5].value = &flags;
110 bufs[5].length = sizeof(flags);
112 /* sign all the bufs except HMAC */
113 rc = sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs, numbufs - 1,
114 EVP_sha256(), &skc->sc_hmac);
118 bufs[6] = skc->sc_hmac;
119 rc = sk_encode_netstring(bufs, numbufs, &cred->lc_mech_token);
123 printerr(2, "Created netstring of %zd bytes\n",
124 cred->lc_mech_token.length);
129 static int lgss_sk_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
130 gss_buffer_desc *ctx_token)
132 struct sk_cred *skc = cred->lc_mech_cred;
133 gss_buffer_desc bufs[2];
138 i = sk_decode_netstring(bufs, numbufs, token);
140 printerr(0, "Failed to decode netstring\n");
144 /* decoded buffers from server should be:
145 * bufs[0] = sc_pub_key
146 * bufs[1] = sc_hmac */
147 rc = sk_verify_hmac(skc, bufs, numbufs - 1, EVP_sha256(), &bufs[1]);
148 if (rc != GSS_S_COMPLETE) {
149 printerr(0, "Invalid HMAC receieved: 0x%x\n", rc);
153 rc = sk_compute_key(skc, &bufs[0]);
154 if (rc == GSS_S_DEFECTIVE_TOKEN) {
155 /* Defective token for short key means we need to retry
156 * because there is a chance that the parameters generated
157 * resulted in a key that is 1 byte short */
158 printerr(0, "Short key computed, must retry\n");
160 } else if (rc != GSS_S_COMPLETE) {
161 printerr(0, "Failed to compute session key: 0x%x\n", rc);
165 rc = sk_kdf(skc, cred->lc_self_nid, &cred->lc_mech_token);
167 printerr(0, "Failed to calulate derived key\n");
171 if (sk_serialize_kctx(skc, ctx_token)) {
172 printerr(0, "Failed to serialize context for kernel\n");
179 struct lgss_mech_type lgss_mech_sk = {
181 .lmt_mech_n = LGSS_MECH_SK,
182 .lmt_prepare_cred = lgss_sk_prepare_cred,
183 .lmt_release_cred = lgss_sk_release_cred,
184 .lmt_using_cred = lgss_sk_using_cred,
185 .lmt_validate_cred = lgss_sk_validate_cred,