~ubuntu-branches/ubuntu/natty/freeradius/natty-updates

« back to all changes in this revision

Viewing changes to src/modules/rlm_otp/cardops/cryptocard.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Hampson
  • Date: 2006-01-15 13:34:13 UTC
  • mto: (3.1.3 dapper) (4.1.3 sid) (1.1.14 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060115133413-zo1dslttvdoalqym
Tags: upstream-1.1.0
ImportĀ upstreamĀ versionĀ 1.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * cryptocard.c
 
3
 * $Id: cryptocard.c,v 1.39.2.1 2005/12/08 01:30:54 fcusack Exp $
 
4
 *
 
5
 *   This program is free software; you can redistribute it and/or modify
 
6
 *   it under the terms of the GNU General Public License as published by
 
7
 *   the Free Software Foundation; either version 2 of the License, or
 
8
 *   (at your option) any later version.
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU General Public License for more details.
 
14
 *
 
15
 *   You should have received a copy of the GNU General Public License
 
16
 *   along with this program; if not, write to the Free Software
 
17
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 * Copyright 2005 TRI-D Systems, Inc.
 
20
 */
 
21
 
 
22
#include <inttypes.h>
 
23
#include <string.h>
 
24
#include <time.h>
 
25
 
 
26
#include "../otp.h"
 
27
#include "../otp_cardops.h"
 
28
#include "cryptocard.h"
 
29
 
 
30
/* Card name to feature mask mappings */
 
31
static struct {
 
32
  const char *name;
 
33
  uint32_t fm;
 
34
} card[] = {
 
35
  { "cryptocard-h8-rc", CRYPTOCARD_H8_RC },
 
36
  { "cryptocard-d8-rc", CRYPTOCARD_D8_RC },
 
37
  { "cryptocard-h7-rc", CRYPTOCARD_H7_RC },
 
38
  { "cryptocard-d7-rc", CRYPTOCARD_D7_RC },
 
39
  { "cryptocard-h8-es", CRYPTOCARD_H8_ES },
 
40
  { "cryptocard-d8-es", CRYPTOCARD_D8_ES },
 
41
  { "cryptocard-h7-es", CRYPTOCARD_H7_ES },
 
42
  { "cryptocard-d7-es", CRYPTOCARD_D7_ES },
 
43
  { "cryptocard-h8-rs", CRYPTOCARD_H8_RS },
 
44
  { "cryptocard-d8-rs", CRYPTOCARD_D8_RS },
 
45
  { "cryptocard-h7-rs", CRYPTOCARD_H7_RS },
 
46
  { "cryptocard-d7-rs", CRYPTOCARD_D7_RS },
 
47
 
 
48
  { NULL, 0 }                                   /* end of list */
 
49
};
 
50
 
 
51
 
 
52
/*
 
53
 * Convert card name to feature mask.
 
54
 * Returns 0 on success, non-zero otherwise.
 
55
 */
 
56
static int
 
57
cryptocard_name2fm(const char *name, uint32_t *featuremask)
 
58
{
 
59
  int i;
 
60
 
 
61
  for (i = 0; card[i].name; ++i) {
 
62
    if (!strcasecmp(name, card[i].name)) {
 
63
      *featuremask = card[i].fm;
 
64
      return 0;
 
65
    }
 
66
  }
 
67
  return 1;
 
68
}
 
69
 
 
70
 
 
71
/*
 
72
 * Convert an ASCII keystring to a keyblock.
 
73
 * Returns keylen on success, -1 otherwise.
 
74
 */
 
75
static int
 
76
cryptocard_keystring2keyblock(const char *keystring,
 
77
                              unsigned char keyblock[OTP_MAX_KEY_LEN])
 
78
{
 
79
  /* 64-bit DES key with optional line ending */
 
80
  if ((strlen(keystring) & ~1) != 16)
 
81
    return 1;
 
82
 
 
83
  return otp_keystring2keyblock(keystring, keyblock);
 
84
}
 
85
 
 
86
 
 
87
/*
 
88
 * Set nullstate.
 
89
 * We don't currently support nullstate for CRYPTOCard, so return -1.
 
90
 */
 
91
static int
 
92
cryptocard_nullstate(
 
93
#ifdef __GNUC__
 
94
__attribute__ ((unused))
 
95
#endif
 
96
                      const otp_option_t *opt,
 
97
#ifdef __GNUC__
 
98
__attribute__ ((unused))
 
99
#endif
 
100
                      const otp_card_info_t *card_info,
 
101
#ifdef __GNUC__
 
102
__attribute__ ((unused))
 
103
#endif
 
104
                      otp_user_state_t *user_state, 
 
105
#ifdef __GNUC__
 
106
__attribute__ ((unused))
 
107
#endif
 
108
                      time_t when,
 
109
                      const char *log_prefix)
 
110
{
 
111
  otp_log(OTP_LOG_ERR, "%s: %s: null state not supported for CRYPTOCard",
 
112
          log_prefix, __func__);
 
113
  return -1;
 
114
}
 
115
 
 
116
 
 
117
/*
 
118
 * Return a synchronous challenge.
 
119
 * Returns 0 on success, -1 otherwise.
 
120
 * (-2 rc is for early challenge, N/A for cryptocard.)
 
121
 */
 
122
static int
 
123
cryptocard_challenge(const otp_card_info_t *card_info,
 
124
                     otp_user_state_t *user_state,
 
125
                     unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
 
126
#ifdef __GNUC__
 
127
__attribute__ ((unused))
 
128
#endif
 
129
                     time_t when,
 
130
#ifdef __GNUC__
 
131
__attribute__ ((unused))
 
132
#endif
 
133
                     int twin,
 
134
#ifdef __GNUC__
 
135
__attribute__ ((unused))
 
136
#endif
 
137
                     int ewin,
 
138
                     const char *log_prefix)
 
139
{
 
140
  unsigned char output[8];
 
141
  int i;
 
142
 
 
143
  /* run x99 once on the previous challenge */
 
144
  if (otp_x99_mac(challenge, user_state->clen, output, card_info->keyblock,
 
145
                  log_prefix))
 
146
    return -1;
 
147
 
 
148
  /* convert the mac into the next challenge */
 
149
  for (i = 0; i < 8; ++i) {
 
150
    output[i] &= 0x0f;
 
151
    if (output[i] > 9)
 
152
      output[i] -= 10;
 
153
    output[i] |= 0x30;
 
154
  }
 
155
  (void) memcpy(challenge, output, 8);
 
156
  user_state->clen = 8;
 
157
 
 
158
  return 0;
 
159
}
 
160
 
 
161
 
 
162
/*
 
163
 * Return the expected card response for a given challenge.
 
164
 * Returns 0 on success, non-zero otherwise.
 
165
 *
 
166
 * The X9.9 MAC is used by CRYPTOcard in the following manner:
 
167
 *
 
168
 * 1. Convert the challenge to ASCII (eg "12345" -> 0x3132333435).
 
169
 *    We don't actually do a conversion, the challenge is already ASCII.
 
170
 *    Note that Secure Computing SafeWord Gold/Platinum tokens can use
 
171
 *    "raw" challenge bytes.
 
172
 * 2. Use the challenge as the plaintext input to the X9.9 MAC algorithm.
 
173
 *
 
174
 * 3. Convert the 32 bit MAC to ASCII (eg 0x1234567f -> "1234567f").
 
175
 *    Note that SafeWord Gold/Platinum tokens can display a 64 bit MAC.
 
176
 * 4. Possibly apply transformations on chars "a" thru "f".
 
177
 * 5. Truncate the response for 7 digit display modes.
 
178
 */
 
179
static int
 
180
cryptocard_response(otp_card_info_t *card_info,
 
181
                    const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
 
182
                    size_t len, char response[OTP_MAX_RESPONSE_LEN + 1],
 
183
                    const char *log_prefix)
 
184
{
 
185
  unsigned char output[8];
 
186
  const char *conversion;
 
187
 
 
188
  /* Step 1, 2. */
 
189
  if (otp_x99_mac(challenge, len, output,
 
190
                  card_info->keyblock, log_prefix) !=0)
 
191
    return 1;
 
192
 
 
193
  /* Setup for step 4. */
 
194
  if (card_info->featuremask & OTP_CF_DD)
 
195
    conversion = otp_cc_dec_conversion;
 
196
  else
 
197
    conversion = otp_hex_conversion;
 
198
 
 
199
  /* Step 3, 4. */
 
200
  (void) otp_keyblock2keystring(response, output, 4, conversion);
 
201
 
 
202
  /* Step 5. */
 
203
  if (card_info->featuremask & OTP_CF_R7)
 
204
    (void) memmove(&response[3], &response[4], 5);
 
205
 
 
206
  return 0;
 
207
}
 
208
 
 
209
 
 
210
/*
 
211
 * Update rd (there is no csd for cryptocard).
 
212
 * Returns 0 if succesful, -1 otherwise.
 
213
 */
 
214
static int
 
215
cryptocard_updatecsd(otp_user_state_t *user_state,
 
216
#ifdef __GNUC__
 
217
__attribute__ ((unused))
 
218
#endif
 
219
                     time_t when,
 
220
#ifdef __GNUC__
 
221
__attribute__ ((unused))
 
222
#endif
 
223
                     int twin,
 
224
                     int ewin,
 
225
                     int auth_rc)
 
226
{
 
227
  if (auth_rc == OTP_RC_OK)
 
228
    user_state->rd[0] = '\0';                           /* reset */
 
229
  else
 
230
    (void) sprintf(user_state->rd, "%" PRIx32,
 
231
                   (int32_t) ewin);                     /* rwindow candidate */
 
232
 
 
233
  return 0;
 
234
}
 
235
 
 
236
 
 
237
/*
 
238
 * Determine if a window position if consecutive relative to a saved
 
239
 * (rwindow candidate) window position, for rwindow override.
 
240
 * user_state contains the previous auth position, twin and ewin the current.
 
241
 * Returns 1 on success (consecutive), 0 otherwise.
 
242
 */
 
243
static int
 
244
cryptocard_isconsecutive(
 
245
#ifdef __GNUC__
 
246
__attribute__ ((unused))
 
247
#endif
 
248
                         const otp_card_info_t *card_info,
 
249
                         const otp_user_state_t *user_state,
 
250
                         int thisewin, const char *log_prefix)
 
251
{
 
252
  int nextewin;
 
253
 
 
254
  /* extract the saved rwindow candidate position */
 
255
  if (sscanf(user_state->rd, "%" SCNx32, &nextewin) != 1) {
 
256
    otp_log(OTP_LOG_ERR, "%s: %s: invalid rwindow data for [%s]",
 
257
            log_prefix, __func__, card_info->username);
 
258
    return 0;
 
259
  }
 
260
  nextewin++;
 
261
 
 
262
  /* Is this the next passcode? */
 
263
  if (thisewin == nextewin)
 
264
    return 1;   /* yes */
 
265
  else
 
266
    return 0;   /* no */
 
267
}
 
268
 
 
269
 
 
270
/* no twin so just return 0 */
 
271
static int
 
272
cryptocard_maxtwin(
 
273
#ifdef __GNUC__
 
274
__attribute__ ((unused))
 
275
#endif
 
276
                    const otp_card_info_t *card_info,
 
277
#ifdef __GNUC__
 
278
__attribute__ ((unused))
 
279
#endif
 
280
                    const char csd[OTP_MAX_CSD_LEN + 1])
 
281
{
 
282
  return 0;
 
283
}
 
284
 
 
285
 
 
286
/* return human-readable challenge */
 
287
static char *
 
288
cryptocard_printchallenge(char s[OTP_MAX_CHALLENGE_LEN * 2 + 1],
 
289
                          const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
 
290
                          size_t len)
 
291
{
 
292
  /* cryptocard challenge is implicitly ASCII */
 
293
  (void) memcpy(s, challenge, len);
 
294
  s[len] = '\0';
 
295
  return s;
 
296
}
 
297
 
 
298
 
 
299
/* cardops instance */
 
300
static cardops_t cryptocard_cardops = {
 
301
  .prefix               = "cryptocard",
 
302
  .prefix_len           = 10, /* strlen("cryptocard") */
 
303
 
 
304
  .name2fm              = cryptocard_name2fm,
 
305
  .keystring2keyblock   = cryptocard_keystring2keyblock,
 
306
  .nullstate            = cryptocard_nullstate,
 
307
  .challenge            = cryptocard_challenge,
 
308
  .response             = cryptocard_response,
 
309
  .updatecsd            = cryptocard_updatecsd,
 
310
  .isconsecutive        = cryptocard_isconsecutive,
 
311
  .maxtwin              = cryptocard_maxtwin,
 
312
  .printchallenge       = cryptocard_printchallenge,
 
313
};
 
314
 
 
315
 
 
316
/* constructor */
 
317
void
 
318
cryptocard_init(void)
 
319
{
 
320
  if (otp_num_cardops == OTP_MAX_VENDORS) {
 
321
    otp_log(OTP_LOG_ERR, "cryptocard_init: module limit exceeded");
 
322
    return;
 
323
  }
 
324
 
 
325
  otp_cardops[otp_num_cardops++] = cryptocard_cardops;
 
326
  otp_log(OTP_LOG_DEBUG, "cryptocard_init: loaded");
 
327
}