*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2005 TRI-D Systems, Inc.
+ * Copyright 2005,2006 TRI-D Systems, Inc.
*/
+#include <inttypes.h>
#include <string.h>
+#include <time.h>
#include "../otp.h"
#include "../otp_cardops.h"
{ "cryptocard-d8-rc", CRYPTOCARD_D8_RC },
{ "cryptocard-h7-rc", CRYPTOCARD_H7_RC },
{ "cryptocard-d7-rc", CRYPTOCARD_D7_RC },
+ { "cryptocard-hp-rc", CRYPTOCARD_HP_RC },
+ { "cryptocard-dp-rc", CRYPTOCARD_DP_RC },
{ "cryptocard-h8-es", CRYPTOCARD_H8_ES },
{ "cryptocard-d8-es", CRYPTOCARD_D8_ES },
{ "cryptocard-h7-es", CRYPTOCARD_H7_ES },
{ "cryptocard-d7-es", CRYPTOCARD_D7_ES },
+ { "cryptocard-hp-es", CRYPTOCARD_HP_ES },
+ { "cryptocard-dp-es", CRYPTOCARD_DP_ES },
{ "cryptocard-h8-rs", CRYPTOCARD_H8_RS },
{ "cryptocard-d8-rs", CRYPTOCARD_D8_RS },
{ "cryptocard-h7-rs", CRYPTOCARD_H7_RS },
{ "cryptocard-d7-rs", CRYPTOCARD_D7_RS },
+ { "cryptocard-hp-rs", CRYPTOCARD_HP_RS },
+ { "cryptocard-dp-rs", CRYPTOCARD_DP_RS },
{ NULL, 0 } /* end of list */
};
/*
* Convert an ASCII keystring to a keyblock.
- * Returns 0 on success, non-zero otherwise.
+ * Returns keylen on success, -1 otherwise.
*/
static int
-cryptocard_keystring2keyblock(const char *keystring, unsigned char keyblock[])
+cryptocard_keystring2keyblock(const char *keystring,
+ unsigned char keyblock[OTP_MAX_KEY_LEN])
{
/* 64-bit DES key with optional line ending */
if ((strlen(keystring) & ~1) != 16)
#ifdef __GNUC__
__attribute__ ((unused))
#endif
- const otp_user_info_t *user_info,
+ const otp_option_t *opt,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ const otp_card_info_t *card_info,
#ifdef __GNUC__
__attribute__ ((unused))
#endif
otp_user_state_t *user_state,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ time_t when,
const char *log_prefix)
{
- otp_log(OTP_LOG_ERR, "%s: null state not supported for CRYPTOCard",
- log_prefix);
+ otp_log(OTP_LOG_ERR, "%s: %s: null state not supported for CRYPTOCard",
+ log_prefix, __func__);
return -1;
}
/*
* Return a synchronous challenge.
- * Returns 0 on success, non-zero otherwise.
+ * Returns 0 on success, -1 otherwise.
+ * (-2 rc is for early challenge, N/A for cryptocard.)
*/
static int
-cryptocard_challenge(const otp_user_info_t *user_info,
- otp_user_state_t *user_state, unsigned int ewin,
+cryptocard_challenge(const otp_card_info_t *card_info,
+ otp_user_state_t *user_state,
+ unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ time_t when,
#ifdef __GNUC__
__attribute__ ((unused))
#endif
int twin,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ int ewin,
const char *log_prefix)
{
- char *challenge = user_state->challenge;
unsigned char output[8];
- int i, rc = 0;
+ int i;
- /* CRYPTOCard sync challenges are always 8 bytes. */
- if (strlen(challenge) != 8)
+ /* run x99 once on the previous challenge */
+ if (otp_x99_mac(challenge, user_state->clen, output, card_info->keyblock,
+ log_prefix))
return -1;
- /* iterate ewin times on the challenge */
- while (ewin--) {
- if ((rc = otp_x99_mac(challenge, 8, output, user_info->keyblock,
- log_prefix)) == 0) {
- /* convert the mac into the next challenge */
- for (i = 0; i < 8; ++i) {
- output[i] &= 0x0f;
- if (output[i] > 9)
- output[i] -= 10;
- output[i] |= 0x30;
- }
- (void) memcpy(challenge, output, 8);
- challenge[8] = '\0';
- } else {
- /* something went wrong */
- break;
- }
+ /* convert the mac into the next challenge */
+ for (i = 0; i < 8; ++i) {
+ output[i] &= 0x0f;
+ if (output[i] > 9)
+ output[i] -= 10;
+ output[i] |= 0x30;
}
+ (void) memcpy(challenge, output, 8);
+ user_state->clen = 8;
- return rc;
+ return 0;
}
* 5. Truncate the response for 7 digit display modes.
*/
static int
-cryptocard_response(otp_user_info_t *user_info, otp_user_state_t *user_state,
- char response[OTP_MAX_RESPONSE_LEN + 1],
+cryptocard_response(otp_card_info_t *card_info,
+ const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
+ size_t len, char response[OTP_MAX_RESPONSE_LEN + 1],
const char *log_prefix)
{
- char *challenge = user_state->challenge;
unsigned char output[8];
- char l_response[17];
const char *conversion;
/* Step 1, 2. */
- if (otp_x99_mac(challenge, strlen(challenge), output,
- user_info->keyblock, log_prefix) !=0)
+ if (otp_x99_mac(challenge, len, output,
+ card_info->keyblock, log_prefix) !=0)
return 1;
/* Setup for step 4. */
- if (user_info->featuremask & OTP_CF_DD)
+ if (card_info->featuremask & OTP_CF_DD)
conversion = otp_cc_dec_conversion;
else
conversion = otp_hex_conversion;
/* Step 3, 4. */
- otp_keyblock2keystring(l_response, output, conversion);
- (void) memcpy(response, l_response, 8);
- response[8] = '\0';
+ (void) otp_keyblock2keystring(response, output, 4, conversion);
/* Step 5. */
- if (user_info->featuremask & OTP_CF_R7)
+ if (card_info->featuremask & OTP_CF_R7)
(void) memmove(&response[3], &response[4], 5);
+ else if (card_info->featuremask & OTP_CF_RP)
+ response[3] = '-';
return 0;
}
+/*
+ * Update rd (there is no csd for cryptocard).
+ * Returns 0 if succesful, -1 otherwise.
+ */
+static int
+cryptocard_updatecsd(otp_user_state_t *user_state,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ time_t when,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ int twin,
+ int ewin,
+ int auth_rc)
+{
+ if (auth_rc == OTP_RC_OK)
+ user_state->rd[0] = '\0'; /* reset */
+ else
+ (void) sprintf(user_state->rd, "%" PRIx32,
+ (int32_t) ewin); /* rwindow candidate */
+
+ return 0;
+}
+
+
+/*
+ * Determine if a window position if consecutive relative to a saved
+ * (rwindow candidate) window position, for rwindow override.
+ * user_state contains the previous auth position, twin and ewin the current.
+ * Returns 1 on success (consecutive), 0 otherwise.
+ */
+static int
+cryptocard_isconsecutive(
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ const otp_card_info_t *card_info,
+ const otp_user_state_t *user_state,
+ int thisewin, const char *log_prefix)
+{
+ int nextewin;
+
+ /* extract the saved rwindow candidate position */
+ if (sscanf(user_state->rd, "%" SCNx32, &nextewin) != 1) {
+ otp_log(OTP_LOG_ERR, "%s: %s: invalid rwindow data for [%s]",
+ log_prefix, __func__, card_info->username);
+ return 0;
+ }
+ nextewin++;
+
+ /* Is this the next passcode? */
+ if (thisewin == nextewin)
+ return 1; /* yes */
+ else
+ return 0; /* no */
+}
+
+
+/* no twin so just return 0 */
+static int
+cryptocard_maxtwin(
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ const otp_card_info_t *card_info,
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+ const char csd[OTP_MAX_CSD_LEN + 1])
+{
+ return 0;
+}
+
+
+/* return human-readable challenge */
+static char *
+cryptocard_printchallenge(char s[OTP_MAX_CHALLENGE_LEN * 2 + 1],
+ const unsigned char challenge[OTP_MAX_CHALLENGE_LEN],
+ size_t len)
+{
+ /* cryptocard challenge is implicitly ASCII */
+ (void) memcpy(s, challenge, len);
+ s[len] = '\0';
+ return s;
+}
+
+
/* cardops instance */
static cardops_t cryptocard_cardops = {
.prefix = "cryptocard",
.keystring2keyblock = cryptocard_keystring2keyblock,
.nullstate = cryptocard_nullstate,
.challenge = cryptocard_challenge,
- .response = cryptocard_response
+ .response = cryptocard_response,
+ .updatecsd = cryptocard_updatecsd,
+ .isconsecutive = cryptocard_isconsecutive,
+ .maxtwin = cryptocard_maxtwin,
+ .printchallenge = cryptocard_printchallenge,
};
+
/* constructor */
void
cryptocard_init(void)