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.
25 #include "../otp_cardops.h"
26 #include "cryptocard.h"
28 /* Card name to feature mask mappings */
33 { "cryptocard-h8-rc", CRYPTOCARD_H8_RC },
34 { "cryptocard-d8-rc", CRYPTOCARD_D8_RC },
35 { "cryptocard-h7-rc", CRYPTOCARD_H7_RC },
36 { "cryptocard-d7-rc", CRYPTOCARD_D7_RC },
37 { "cryptocard-h8-es", CRYPTOCARD_H8_ES },
38 { "cryptocard-d8-es", CRYPTOCARD_D8_ES },
39 { "cryptocard-h7-es", CRYPTOCARD_H7_ES },
40 { "cryptocard-d7-es", CRYPTOCARD_D7_ES },
41 { "cryptocard-h8-rs", CRYPTOCARD_H8_RS },
42 { "cryptocard-d8-rs", CRYPTOCARD_D8_RS },
43 { "cryptocard-h7-rs", CRYPTOCARD_H7_RS },
44 { "cryptocard-d7-rs", CRYPTOCARD_D7_RS },
46 { NULL, 0 } /* end of list */
51 * Convert card name to feature mask.
52 * Returns 0 on success, non-zero otherwise.
55 cryptocard_name2fm(const char *name, uint32_t *featuremask)
59 for (i = 0; card[i].name; ++i) {
60 if (!strcasecmp(name, card[i].name)) {
61 *featuremask = card[i].fm;
70 * Convert an ASCII keystring to a keyblock.
71 * Returns 0 on success, non-zero otherwise.
74 cryptocard_keystring2keyblock(const char *keystring, unsigned char keyblock[])
76 /* 64-bit DES key with optional line ending */
77 if ((strlen(keystring) & ~1) != 16)
80 return otp_keystring2keyblock(keystring, keyblock);
86 * We don't currently support nullstate for CRYPTOCard, so return -1.
91 __attribute__ ((unused))
93 const otp_user_info_t *user_info,
95 __attribute__ ((unused))
97 otp_user_state_t *user_state,
98 const char *log_prefix)
100 otp_log(OTP_LOG_ERR, "%s: null state not supported for CRYPTOCard",
107 * Return a synchronous challenge.
108 * Returns 0 on success, non-zero otherwise.
111 cryptocard_challenge(const otp_user_info_t *user_info, unsigned int ewin,
113 __attribute__ ((unused))
116 char challenge[OTP_MAX_CHALLENGE_LEN + 1],
117 const char *log_prefix)
119 unsigned char output[8];
122 /* CRYPTOCard sync challenges are always 8 bytes. */
123 if (strlen(challenge) != 8)
126 /* iterate ewin times on the challenge */
128 if ((rc = otp_x99_mac(challenge, 8, output, user_info->keyblock,
130 /* convert the mac into the next challenge */
131 for (i = 0; i < 8; ++i) {
137 (void) memcpy(challenge, output, 8);
140 /* something went wrong */
150 * Return the expected card response for a given challenge.
151 * Returns 0 on success, non-zero otherwise.
153 * The X9.9 MAC is used by CRYPTOcard in the following manner:
155 * 1. Convert the challenge to ASCII (eg "12345" -> 0x3132333435).
156 * We don't actually do a conversion, the challenge is already ASCII.
157 * Note that Secure Computing SafeWord Gold/Platinum tokens can use
158 * "raw" challenge bytes.
159 * 2. Use the challenge as the plaintext input to the X9.9 MAC algorithm.
161 * 3. Convert the 32 bit MAC to ASCII (eg 0x1234567f -> "1234567f").
162 * Note that SafeWord Gold/Platinum tokens can display a 64 bit MAC.
163 * 4. Possibly apply transformations on chars "a" thru "f".
164 * 5. Truncate the response for 7 digit display modes.
167 cryptocard_response(otp_user_info_t *user_info, const char *challenge,
168 char response[OTP_MAX_RESPONSE_LEN + 1],
169 const char *log_prefix)
171 unsigned char output[8];
173 const char *conversion;
176 if (otp_x99_mac(challenge, strlen(challenge), output,
177 user_info->keyblock, log_prefix) !=0)
180 /* Setup for step 4. */
181 if (user_info->featuremask & OTP_CF_DD)
182 conversion = otp_cc_dec_conversion;
184 conversion = otp_hex_conversion;
187 otp_keyblock2keystring(l_response, output, conversion);
188 (void) memcpy(response, l_response, 8);
192 if (user_info->featuremask & OTP_CF_R7)
193 (void) memmove(&response[3], &response[4], 5);
199 /* cardops instance */
200 static cardops_t cryptocard_cardops = {
201 .prefix = "cryptocard",
202 .prefix_len = 10, /* strlen("cryptocard") */
204 .name2fm = cryptocard_name2fm,
205 .keystring2keyblock = cryptocard_keystring2keyblock,
206 .nullstate = cryptocard_nullstate,
207 .challenge = cryptocard_challenge,
208 .response = cryptocard_response
213 cryptocard_init(void)
215 if (otp_num_cardops == OTP_MAX_VENDORS) {
216 otp_log(OTP_LOG_ERR, "cryptocard_init: module limit exceeded");
220 otp_cardops[otp_num_cardops++] = cryptocard_cardops;
221 otp_log(OTP_LOG_DEBUG, "cryptocard_init: loaded");