1 /* rxgk/rxgk_token.c - Token generation/manuipluation routines for RXGK */
3 * Copyright (C) 2013, 2014 by the Massachusetts Institute of Technology.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Routines to generate, encode, encrypt, decode, and decrypt rxgk tokens.
38 #include <afsconfig.h>
39 #include <afs/param.h>
44 #include <rx/rx_opaque.h>
48 #include "rxgk_private.h"
51 * Copy the fields from a TokenInfo to a Token.
54 tokeninfo_to_token(RXGK_TokenInfo *info, RXGK_Token *token)
57 token->enctype = info->enctype;
58 token->level = info->level;
59 token->lifetime = info->lifetime;
60 token->bytelife = info->bytelife;
61 token->expirationtime = info->expiration;
66 * Take the input RXGK_Token and XDR-encode it, returning the result in 'out'.
67 * The caller is responsible for freeing the memory contained in 'out'.
72 pack_token(RXGK_Token *token, struct rx_opaque *out)
78 memset(&xdrs, 0, sizeof(xdrs));
79 memset(out, 0, sizeof(*out));
81 if (!xdr_RXGK_Token(&xdrs, token)) {
82 ret = RXGEN_SS_MARSHAL;
85 len = xdr_getpos(&xdrs);
87 ret = rx_opaque_alloc(out, len);
92 xdrmem_create(&xdrs, out->val, len, XDR_ENCODE);
93 if (!xdr_RXGK_Token(&xdrs, token)) {
94 rx_opaque_freeContents(out);
95 ret = RXGEN_SS_MARSHAL;
106 * Take the input TokenContainer and XDR-encode it, returning the result
107 * in 'out'. The caller is responsible for freeing the memory contained
113 pack_container(RXGK_TokenContainer *container, struct rx_opaque *out)
119 memset(&xdrs, 0, sizeof(xdrs));
120 xdrlen_create(&xdrs);
121 if (!xdr_RXGK_TokenContainer(&xdrs, container)) {
122 ret = RXGEN_SS_MARSHAL;
125 len = xdr_getpos(&xdrs);
127 ret = rx_opaque_alloc(out, len);
132 xdrmem_create(&xdrs, out->val, len, XDR_ENCODE);
133 if (!xdr_RXGK_TokenContainer(&xdrs, container)) {
134 rx_opaque_freeContents(out);
135 ret = RXGEN_SS_MARSHAL;
146 * Take the input token, encode it, encrypt that blob, populate a
147 * TokenContainer with the encrypted token, kvno, and enctype, and encode
148 * the resulting TokenContainer into 'out'.
153 pack_wrap_token(rxgk_key server_key, afs_int32 kvno, afs_int32 enctype,
154 RXGK_Token *token, struct rx_opaque *out)
156 struct rx_opaque packed_token = RX_EMPTY_OPAQUE;
157 struct rx_opaque encrypted_token = RX_EMPTY_OPAQUE;
158 RXGK_TokenContainer container;
161 memset(&container, 0, sizeof(container));
163 /* XDR-encode the token in to packed_token. */
164 ret = pack_token(token, &packed_token);
168 ret = rxgk_encrypt_in_key(server_key, RXGK_SERVER_ENC_TOKEN, &packed_token,
172 ret = rx_opaque_populate(&container.encrypted_token, encrypted_token.val,
173 encrypted_token.len);
176 container.kvno = kvno;
177 container.enctype = enctype;
179 /* Now the token container is populated; time to encode it into 'out'. */
180 ret = pack_container(&container, out);
183 rx_opaque_freeContents(&packed_token);
184 rx_opaque_freeContents(&encrypted_token);
185 rx_opaque_freeContents(&container.encrypted_token);
190 * Print an rxgk token with random key, returning key and token
192 * Print a token (with empty identity list) with a random master key,
193 * and encrypt it in the specified key/kvno/enctype. Return the master
194 * key as well as the token, so that the token is usable.
196 * The caller must free k0 with release_key().
198 * @param[out] out The printed token (RXGK_TokenContainer).
199 * @param[in] input_info Parameters describing the token to be printed.
200 * @param[in] key The token-encrypting key.
201 * @param[in] kvno The kvno of key.
202 * @param[in] enctype The enctype of key.
203 * @param[out] k0_out The token master key.
204 * @return rxgk error codes.
207 rxgk_print_token_and_key(struct rx_opaque *out, RXGK_TokenInfo *input_info,
208 rxgk_key key, afs_int32 kvno, afs_int32 enctype,
211 struct rx_opaque k0_data = RX_EMPTY_OPAQUE;
218 len = rxgk_etype_to_len(input_info->enctype);
224 ret = rxgk_nonce(&k0_data, len);
228 ret = rxgk_make_key(&k0, k0_data.val, k0_data.len, input_info->enctype);
232 ret = rxgk_print_token(out, input_info, &k0_data, key, kvno, enctype);
240 rx_opaque_freeContents(&k0_data);
241 rxgk_release_key(&k0);
246 * Helper functions for rxgk_extract_token.
249 unpack_container(RXGK_Data *in, RXGK_TokenContainer *container)
253 memset(&xdrs, 0, sizeof(xdrs));
255 xdrmem_create(&xdrs, in->val, in->len, XDR_DECODE);
256 if (!xdr_RXGK_TokenContainer(&xdrs, container)) {
258 return RXGEN_SS_UNMARSHAL;
265 decrypt_token(struct rx_opaque *enctoken, afs_int32 kvno, afs_int32 enctype,
266 rxgk_getkey_func getkey, void *rock, RXGK_Data *out)
268 rxgk_key service_key = NULL;
271 if (kvno <= 0 || enctype <= 0) {
272 ret = RXGK_BAD_TOKEN;
276 ret = getkey(rock, &kvno, &enctype, &service_key);
279 ret = rxgk_decrypt_in_key(service_key, RXGK_SERVER_ENC_TOKEN, enctoken,
283 rxgk_release_key(&service_key);
288 unpack_token(RXGK_Data *in, RXGK_Token *token)
292 memset(&xdrs, 0, sizeof(xdrs));
294 xdrmem_create(&xdrs, in->val, in->len, XDR_DECODE);
295 if (!xdr_RXGK_Token(&xdrs, token)) {
297 return RXGEN_SS_UNMARSHAL;
304 * Extract a cleartext RXGK_Token from a packed RXGK_TokenContainer
306 * Given an XDR-encoded RXGK_TokenContainer, extract/decrypt the contents
307 * into an RXGK_Token.
309 * The caller must free the returned token with xdr_free.
311 * @param[in] tc The RXGK_TokenContainer to unpack.
312 * @param[out] out The extracted RXGK_Token.
313 * @param[in] getkey The getkey function used to decrypt the token.
314 * @param[in] rock Data to pass to getkey.
315 * @return rxgk error codes.
318 rxgk_extract_token(RXGK_Data *tc, RXGK_Token *out, rxgk_getkey_func getkey,
321 RXGK_TokenContainer container;
322 struct rx_opaque packed_token = RX_EMPTY_OPAQUE;
325 memset(&container, 0, sizeof(container));
327 ret = unpack_container(tc, &container);
330 ret = decrypt_token(&container.encrypted_token, container.kvno,
331 container.enctype, getkey, rock, &packed_token);
334 ret = unpack_token(&packed_token, out);
337 xdr_free((xdrproc_t)xdr_RXGK_TokenContainer, &container);
338 xdr_free((xdrproc_t)xdr_RXGK_Data, &packed_token);
342 /* NEVER call this function directly (except from rxgk_make_token or
343 * rxgk_print_token). Call rxgk_make_token or rxgk_print_token instead. See
344 * rxgk_make_token for info about our arguments. */
346 make_token(struct rx_opaque *out, RXGK_TokenInfo *info,
347 struct rx_opaque *k0, PrAuthName *identities,
348 int nids, rxgk_key key, afs_int32 kvno, afs_int32 enctype)
353 memset(&token, 0, sizeof(token));
354 memset(out, 0, sizeof(*out));
357 ret = RXGK_INCONSISTENCY;
361 /* Get the tokeninfo values from the authoritative source. */
362 tokeninfo_to_token(info, &token);
364 /* Create the rest of the token. */
365 ret = rx_opaque_populate(&token.K0, k0->val, k0->len);
368 token.identities.len = (afs_uint32)nids;
369 token.identities.val = identities;
370 ret = pack_wrap_token(key, kvno, enctype, &token, out);
376 * We need to free the contents in 'token', but don't free
377 * token.identities. The pointer for that was given to us by our caller;
378 * they'll manage the memory for it.
380 memset(&token.identities, 0, sizeof(token.identities));
381 xdr_free((xdrproc_t)xdr_RXGK_Token, &token);
386 * Create an rxgk token
388 * Create a token from the specified TokenInfo, key, start time, and lists
389 * of identities. Encrypts the token and stores it as an rx_opaque.
391 * Note that you cannot make printed tokens with this function ('nids' must be
392 * greater than 0). This is a deliberate restriction to try to avoid
393 * accidentally creating printed tokens. Use rxgk_print_token() instead to
394 * make printed tokens.
396 * @param[out] out The encoded rxgk token (RXGK_TokenContainer).
397 * @param[in] info RXGK_Tokeninfo describing the token to be produced.
398 * @param[in] k0 The token master key.
399 * @param[in] identities The list of identities to be included in the token.
400 * @param[in] nids The number of identities in the identities list (must
402 * @param[in] key The token-encrypting key to use.
403 * @param[in] kvno The kvno of key.
404 * @param[in] enctype The enctype of key.
405 * @return rxgk error codes.
408 rxgk_make_token(struct rx_opaque *out, RXGK_TokenInfo *info,
409 struct rx_opaque *k0, PrAuthName *identities,
410 int nids, rxgk_key key, afs_int32 kvno, afs_int32 enctype)
412 if (nids == 0 || identities == NULL) {
413 /* You cannot make printed tokens with this function; use
414 * rxgk_print_token instead. */
415 memset(out, 0, sizeof(*out));
416 return RXGK_INCONSISTENCY;
418 return make_token(out, info, k0, identities, nids, key, kvno, enctype);
421 /* This lifetime is in seconds. */
422 #define DEFAULT_LIFETIME (60 * 60 * 10)
423 /* The bytelife is log_2(bytes). */
424 #define DEFAULT_BYTELIFE 30
426 * Create a printed rxgk token
428 * Print a token (with empty identity list) where the master key (k0)
429 * already exists, and encrypt it in the specified key/kvno/enctype.
431 * @param[out] out The printed token (RXGK_TokenContainer).
432 * @param[in] input_info Parameters describing the token to be printed.
433 * @param[in] k0 The master key to use for the token.
434 * @param[in] key The token-encrypting key.
435 * @param[in] kvno The kvno of key.
436 * @param[in] enctype The enctype of key.
437 * @return rxgk error codes.
440 rxgk_print_token(struct rx_opaque *out, RXGK_TokenInfo *input_info,
441 struct rx_opaque *k0, rxgk_key key, afs_int32 kvno,
446 memset(&info, 0, sizeof(info));
448 info.enctype = input_info->enctype;
449 info.level = input_info->level;
450 info.lifetime = DEFAULT_LIFETIME;
451 info.bytelife = DEFAULT_BYTELIFE;
452 info.expiration = RXGK_NEVERDATE;
454 return make_token(out, &info, k0, NULL, 0, key, kvno, enctype);