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.
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.
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
19 * Copyright 2005 TRI-D Systems, Inc.
27 #include "../otp_cardops.h"
28 #include "cryptocard.h"
30 /* Card name to feature mask mappings */
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 },
48 { NULL, 0 } /* end of list */
53 * Convert card name to feature mask.
54 * Returns 0 on success, non-zero otherwise.
57 cryptocard_name2fm(const char *name, uint32_t *featuremask)
61 for (i = 0; card[i].name; ++i) {
62 if (!strcasecmp(name, card[i].name)) {
63 *featuremask = card[i].fm;
72 * Convert an ASCII keystring to a keyblock.
73 * Returns 0 on success, non-zero otherwise.
76 cryptocard_keystring2keyblock(const char *keystring,
77 unsigned char keyblock[OTP_MAX_KEY_LEN])
79 /* 64-bit DES key with optional line ending */
80 if ((strlen(keystring) & ~1) != 16)
83 return otp_keystring2keyblock(keystring, keyblock);
89 * We don't currently support nullstate for CRYPTOCard, so return -1.
94 __attribute__ ((unused))
96 const otp_option_t *opt,
98 __attribute__ ((unused))
100 const otp_user_info_t *user_info,
102 __attribute__ ((unused))
104 otp_user_state_t *user_state,
106 __attribute__ ((unused))
109 const char *log_prefix)
111 otp_log(OTP_LOG_ERR, "%s: null state not supported for CRYPTOCard",
118 * Return a synchronous challenge.
119 * Returns 0 on success, non-zero otherwise.
122 cryptocard_challenge(const otp_user_info_t *user_info,
124 __attribute__ ((unused))
126 const char csd[OTP_MAX_CSD_LEN + 1],
128 __attribute__ ((unused))
131 char challenge[OTP_MAX_CHALLENGE_LEN + 1],
133 __attribute__ ((unused))
137 __attribute__ ((unused))
140 const char *log_prefix)
142 unsigned char output[8];
145 /* CRYPTOCard sync challenges are always 8 bytes. */
146 if (strlen(challenge) != 8)
149 /* run x99 once on the challenge */
150 if (otp_x99_mac(challenge, 8, output, user_info->keyblock, log_prefix))
153 /* convert the mac into the next challenge */
154 for (i = 0; i < 8; ++i) {
160 (void) memcpy(challenge, output, 8);
168 * Return the expected card response for a given challenge.
169 * Returns 0 on success, non-zero otherwise.
171 * The X9.9 MAC is used by CRYPTOcard in the following manner:
173 * 1. Convert the challenge to ASCII (eg "12345" -> 0x3132333435).
174 * We don't actually do a conversion, the challenge is already ASCII.
175 * Note that Secure Computing SafeWord Gold/Platinum tokens can use
176 * "raw" challenge bytes.
177 * 2. Use the challenge as the plaintext input to the X9.9 MAC algorithm.
179 * 3. Convert the 32 bit MAC to ASCII (eg 0x1234567f -> "1234567f").
180 * Note that SafeWord Gold/Platinum tokens can display a 64 bit MAC.
181 * 4. Possibly apply transformations on chars "a" thru "f".
182 * 5. Truncate the response for 7 digit display modes.
185 cryptocard_response(otp_user_info_t *user_info,
187 __attribute__ ((unused))
190 const char *challenge,
191 char response[OTP_MAX_RESPONSE_LEN + 1],
192 const char *log_prefix)
194 unsigned char output[8];
196 const char *conversion;
199 if (otp_x99_mac(challenge, strlen(challenge), output,
200 user_info->keyblock, log_prefix) !=0)
203 /* Setup for step 4. */
204 if (user_info->featuremask & OTP_CF_DD)
205 conversion = otp_cc_dec_conversion;
207 conversion = otp_hex_conversion;
210 otp_keyblock2keystring(l_response, output, conversion);
211 (void) memcpy(response, l_response, 8);
215 if (user_info->featuremask & OTP_CF_R7)
216 (void) memmove(&response[3], &response[4], 5);
222 /* no csd so just return success */
224 cryptocard_updatecsd(
226 __attribute__ ((unused))
228 const otp_user_info_t *user_info,
230 __attribute__ ((unused))
232 otp_user_state_t *user_state,
234 __attribute__ ((unused))
236 const char challenge[OTP_MAX_CHALLENGE_LEN + 1],
238 __attribute__ ((unused))
242 __attribute__ ((unused))
246 __attribute__ ((unused))
250 __attribute__ ((unused))
252 const char *log_prefix)
258 /* events can only go forward, so an auth can never be too early */
262 __attribute__ ((unused))
264 const otp_user_state_t *user_state,
266 __attribute__ ((unused))
270 __attribute__ ((unused))
274 __attribute__ ((unused))
276 const char *log_prefix)
282 /* no twin so just return 0 */
286 __attribute__ ((unused))
294 /* no twin so just return 0 */
298 __attribute__ ((unused))
300 const otp_user_info_t *user_info,
302 __attribute__ ((unused))
304 const char csd[OTP_MAX_CSD_LEN + 1],
306 __attribute__ ((unused))
314 /* no twin so just return current time */
316 cryptocard_twin2authtime(
318 __attribute__ ((unused))
320 const char csd[OTP_MAX_CSD_LEN + 1],
323 __attribute__ ((unused))
327 __attribute__ ((unused))
329 const char *log_prefix)
335 /* cardops instance */
336 static cardops_t cryptocard_cardops = {
337 .prefix = "cryptocard",
338 .prefix_len = 10, /* strlen("cryptocard") */
340 .name2fm = cryptocard_name2fm,
341 .keystring2keyblock = cryptocard_keystring2keyblock,
342 .nullstate = cryptocard_nullstate,
343 .challenge = cryptocard_challenge,
344 .response = cryptocard_response,
345 .updatecsd = cryptocard_updatecsd,
346 .isearly = cryptocard_isearly,
347 .nexttwin = cryptocard_nexttwin,
348 .maxtwin = cryptocard_maxtwin,
349 .twin2authtime = cryptocard_twin2authtime
355 cryptocard_init(void)
357 if (otp_num_cardops == OTP_MAX_VENDORS) {
358 otp_log(OTP_LOG_ERR, "cryptocard_init: module limit exceeded");
362 otp_cardops[otp_num_cardops++] = cryptocard_cardops;
363 otp_log(OTP_LOG_DEBUG, "cryptocard_init: loaded");