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

« back to all changes in this revision

Viewing changes to src/modules/rlm_x99_token/crcalc.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
 
 * crcalc.c
3
 
 *
4
 
 *   This program is free software; you can redistribute it and/or modify
5
 
 *   it under the terms of the GNU General Public License as published by
6
 
 *   the Free Software Foundation; either version 2 of the License, or
7
 
 *   (at your option) any later version.
8
 
 *
9
 
 *   This program is distributed in the hope that it will be useful,
10
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 *   GNU General Public License for more details.
13
 
 *
14
 
 *   You should have received a copy of the GNU General Public License
15
 
 *   along with this program; if not, write to the Free Software
16
 
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 *
18
 
 * Copyright 2001,2002 Google, Inc.
19
 
 */
20
 
 
21
 
#include <stdio.h>
22
 
#include <string.h>
23
 
#include <ctype.h>
24
 
#include <openssl/des.h>
25
 
 
26
 
/*
27
 
 * Convert the ASCII string representation of a DES key to raw octets.
28
 
 * keyblock is filled in.  Returns 0 on success, -1 otherwise.
29
 
 */
30
 
static
31
 
int string_to_keyblock(const char *s, des_cblock keyblock)
32
 
{
33
 
    int i;
34
 
 
35
 
    if (s == NULL || strlen(s) < 16)
36
 
        return -1;
37
 
 
38
 
    /*
39
 
     * We could just use sscanf, but we do this a lot, and have very
40
 
     * specific needs, and it's easy to implement, so let's go for it!
41
 
     */
42
 
    for (i = 0; i < 8; ++i) {
43
 
        unsigned int n[2];
44
 
 
45
 
        n[0] = *s++ - '0';
46
 
        n[1] = *s++ - '0';
47
 
        if (n[0] > 9) {
48
 
            n[0] -= 'a' - '9' - 1;
49
 
        }
50
 
        if (n[1] > 9) {
51
 
            n[1] -= 'a' - '9' - 1;
52
 
        }
53
 
 
54
 
        keyblock[i]  = n[0] << 4;
55
 
        keyblock[i] += n[1];
56
 
    }
57
 
    return 0;
58
 
}
59
 
 
60
 
 
61
 
/* Character maps for generic hex and vendor specific decimal modes */
62
 
static const char ascii_conversion[]  = "0123456789abcdef";
63
 
static const char cc_dec_conversion[] = "0123456789012345";
64
 
 
65
 
/*
66
 
 * Convert a DES keyblock to an ASCII string.
67
 
 * Fills in s, which must point to at least 17 bytes of space.
68
 
 * Note that each octet expands into 2 hex digits in ASCII (0xAA -> 0x4141);
69
 
 * add a NULL string terminator and you get the 17 byte requirement.
70
 
 */
71
 
static
72
 
void keyblock_to_string(char *s, const des_cblock keyblock,
73
 
                        const char conversion[17])
74
 
{
75
 
    int i;
76
 
 
77
 
    for (i = 0; i < 8; ++i) {
78
 
        unsigned n[2];
79
 
 
80
 
        n[0] = (keyblock[i] >> 4) & 0x0f;
81
 
        n[1] = keyblock[i] & 0x0f;
82
 
        s[2 * i + 0] = conversion[n[0]];
83
 
        s[2 * i + 1] = conversion[n[1]];
84
 
    }
85
 
    s[16] = '\0';
86
 
}
87
 
 
88
 
 
89
 
int
90
 
main(int argc, char *argv[])
91
 
{
92
 
    /* ARGSUSED */
93
 
    char ascii_key[17];
94
 
    char challenge[10], response[9], response_long[17];
95
 
    char buf[BUFSIZ];
96
 
    des_cblock keyblock;
97
 
    des_key_schedule ks;
98
 
    char *p;
99
 
    int i, rc;
100
 
 
101
 
    memset(ascii_key, 0, sizeof(ascii_key));
102
 
 
103
 
    /* get the key */
104
 
    fprintf(stdout, "Enter a DES key as 16 hex digits (spaces allowed): ");
105
 
    fgets(buf, sizeof(buf), stdin);
106
 
    buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
107
 
    p = buf;
108
 
 
109
 
    /* setup key */
110
 
    if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
111
 
        p += 2;
112
 
    i = 0;
113
 
    while (*p) {
114
 
        if (*p == ' ') {
115
 
            p++;
116
 
            continue;
117
 
        }
118
 
        if (*p < '0' || *p > '9') {
119
 
            if (*p < 'a' || *p > 'f') {
120
 
                if (*p < 'A' || *p > 'F') {
121
 
                    fprintf(stderr, "bad key\n");
122
 
                    exit(1);
123
 
                }
124
 
            }
125
 
        }
126
 
        if (i > 15) {
127
 
            fprintf(stderr, "key too long\n");
128
 
            exit(1);
129
 
        }
130
 
        ascii_key[i++] = tolower((int) *p++);
131
 
    }
132
 
    if (strlen(ascii_key) < 16) {
133
 
        fprintf(stderr, "key too short\n");
134
 
        exit(1);
135
 
    }
136
 
    string_to_keyblock(ascii_key, keyblock);
137
 
 
138
 
    /* verify the key. */
139
 
key_verify:
140
 
    if ((rc = des_set_key_checked(&keyblock, ks)) != 0) {
141
 
        fprintf(stderr, "key %s\n",
142
 
               rc == -1 ? "has incorrect parity" : "is weak");
143
 
        if (rc == -1) {
144
 
            des_set_odd_parity(&keyblock);
145
 
            goto key_verify;
146
 
        }
147
 
        else {
148
 
            exit(1);
149
 
        }
150
 
    }
151
 
 
152
 
    fprintf(stdout, "Enter the challenge: ");
153
 
    fgets(challenge, sizeof(challenge), stdin);
154
 
    challenge[strlen(challenge) - 1] = '\0'; /* strip '\n' */
155
 
    /* encrypt null block if no challenge */
156
 
 
157
 
    /*
158
 
     * Calculate the response.  The algorithm is:
159
 
     * 1. Convert the challenge to ASCII bytes (eg "12345" -> 0x3132333435).
160
 
     * 2. Pad LSB of a 64-bit block w/ 0 bytes if challenge < 8 bytes (digits).
161
 
     * 3. Encrypt w/ DES (whose block size is 64 bits).
162
 
     * 4. Convert the most significant 32 bits of the ciphertext
163
 
     *    to 8 hex digits as a string (eg 0x1234567f -> "1234567f").
164
 
     */
165
 
    {
166
 
        des_cblock input, output;
167
 
 
168
 
        /* Step 1, 2 (conversion is already done, just copy and pad) */
169
 
        (void) memset(input, 0, sizeof(input));
170
 
        (void) memcpy(input, challenge, strlen(challenge));
171
 
 
172
 
        /* Step 3 */
173
 
        des_ecb_encrypt(&input, &output, ks, 1);
174
 
 
175
 
        /* Step 4, 5 */
176
 
        keyblock_to_string(response_long, output, ascii_conversion);
177
 
        (void) memcpy(response, response_long, 8);
178
 
        response[8] = '\0';
179
 
        memcpy(challenge, output, 8);
180
 
        challenge[8] = '\0';
181
 
    }
182
 
 
183
 
    /* calculate the next challenge for cryptocard */
184
 
    for (i = 0; i < 8; ++i) {
185
 
        challenge[i] &= 0x0f;
186
 
        if (challenge[i] > 9)
187
 
            challenge[i] -= 10;
188
 
        challenge[i] |= 0x30;
189
 
    }
190
 
 
191
 
    fprintf(stdout, "response is %s [%s]\n", response, &response_long[8]);
192
 
    fprintf(stdout, "next challenge is %s\n", challenge);
193
 
    exit(0);
194
 
}
195
 
 
196