The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
decrypt.c
Go to the documentation of this file.
1 /**
2  * $Id: 3fd970ccc54d884a5eba35dd6c1ef33eed663d40 $
3  * @file decrypt.c
4  * @brief Authentication for yubikey OTP tokens using the yubikey library.
5  *
6  * @author Arran Cudbard-Bell (a.cudbardb@networkradius.com)
7  * @copyright 2013 The FreeRADIUS server project
8  * @copyright 2013 Network RADIUS (legal@networkradius.com)
9  */
10 #include "rlm_yubikey.h"
11 
12 #ifdef HAVE_YUBIKEY
13 
14 /** Decrypt a Yubikey OTP AES block
15  *
16  * @param[out] p_result The result of attempt to decrypt the token.
17  * @param[in] mctx call data.
18  * @param[in] request The current request.
19  * @param[in] passcode string to decrypt.
20  */
21 unlang_action_t rlm_yubikey_decrypt(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
22 {
23  rlm_yubikey_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_yubikey_t);
24  uint32_t counter, timestamp;
25  yubikey_token_st token;
26 
27  fr_pair_t *key, *vp;
28 
29  key = fr_pair_find_by_da_nested(&request->control_pairs, NULL, attr_yubikey_key);
30  if (!key) {
31  REDEBUG("Yubikey-Key attribute not found in control list, can't decrypt OTP data");
33  }
34 
35  if (key->vp_length != YUBIKEY_KEY_SIZE) {
36  REDEBUG("Yubikey-Key length incorrect, expected %u got %zu", YUBIKEY_KEY_SIZE, key->vp_length);
38  }
39 
40  yubikey_parse((uint8_t const *) passcode + inst->id_len, key->vp_octets, &token);
41 
42  /*
43  * Apparently this just uses byte offsets...
44  */
45  if (!yubikey_crc_ok_p((uint8_t *) &token)) {
46  REDEBUG("Decrypting OTP token data failed, rejecting");
48  }
49 
50  RDEBUG2("Token data decrypted successfully");
51 
52  counter = (yubikey_counter(token.ctr) << 8) | token.use;
53  timestamp = (token.tstph << 16) | token.tstpl;
54 
55  RDEBUG2("Private ID : %pH", fr_box_octets(token.uid, YUBIKEY_UID_SIZE));
56  RDEBUG2("Session counter : %u", counter);
57 
58  RDEBUG2("Token timestamp : %u", timestamp);
59 
60  RDEBUG2("Random data : %u", token.rnd);
61  RDEBUG2("CRC data : 0x%x", token.crc);
62 
63  /*
64  * Private ID used for validation purposes
65  */
67  fr_pair_value_memdup(vp, token.uid, YUBIKEY_UID_SIZE, true);
68 
69  /*
70  * Token timestamp
71  */
73  vp->vp_uint32 = timestamp;
74 
75  /*
76  * Token random
77  */
79  vp->vp_uint32 = token.rnd;
80 
81  /*
82  * Combine the two counter fields together so we can do
83  * replay attack checks.
84  */
86  vp->vp_uint32 = counter;
87 
88  /*
89  * Now we check for replay attacks
90  */
91  vp = fr_pair_find_by_da_nested(&request->control_pairs, NULL, attr_yubikey_counter);
92  if (!vp) {
93  RWDEBUG("Yubikey-Counter not found in control list, skipping replay attack checks");
95  }
96 
97  if (counter <= vp->vp_uint32) {
98  REDEBUG("Replay attack detected! Counter value %u, is lt or eq to last known counter value %u",
99  counter, vp->vp_uint32);
101  }
102 
104 }
105 #endif
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define RWDEBUG(fmt,...)
Definition: log.h:361
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition: pair.c:2981
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition: pair.c:770
#define pair_update_request(_attr, _da)
Definition: radclient-ng.c:60
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
fr_dict_attr_t const * attr_yubikey_random
Definition: rlm_yubikey.c:68
fr_dict_attr_t const * attr_yubikey_counter
Definition: rlm_yubikey.c:66
fr_dict_attr_t const * attr_yubikey_key
Definition: rlm_yubikey.c:63
fr_dict_attr_t const * attr_yubikey_timestamp
Definition: rlm_yubikey.c:67
fr_dict_attr_t const * attr_yubikey_private_id
Definition: rlm_yubikey.c:65
unlang_action_t rlm_yubikey_decrypt(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
void * data
Module's instance data.
Definition: module.h:271
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define vp_uint32
Definition: pair.h:123
#define fr_box_octets(_val, _len)
Definition: value.h:288