2 * Copyright (c) 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <krb5_locl.h>
44 struct checksum_type
{
49 void (*checksum
)(void *, size_t, const krb5_keyblock
*, void *);
50 int (*verify
)(void *, size_t, const krb5_keyblock
*, void *);
55 /* values for `flags' */
59 static struct checksum_type
* find_checksum_type(krb5_cksumtype
);
63 NULL_checksum(void *p
, size_t len
, const krb5_keyblock
*k
, void *result
)
68 MD4_checksum(void *p
, size_t len
, const krb5_keyblock
*k
, void *result
)
72 md4_update(&m
, p
, len
);
73 md4_finito(&m
, result
);
77 MD5_checksum(void *p
, size_t len
, const krb5_keyblock
*k
, void *result
)
81 md5_update(&m
, p
, len
);
82 md5_finito(&m
, result
);
86 SHA1_checksum(void *p
, size_t len
, const krb5_keyblock
*k
, void *result
)
90 sha_update(&m
, p
, len
);
91 sha_finito(&m
, result
);
95 CRC_checksum(void *p
, size_t len
, const krb5_keyblock
*k
, void *result
)
98 unsigned char *r
= result
;
100 crc
= crc_update (p
, len
, 0);
102 r
[1] = (crc
>> 8) & 0xff;
103 r
[2] = (crc
>> 16) & 0xff;
104 r
[3] = (crc
>> 24) & 0xff;
108 MD4_DES_checksum (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
114 des_key_schedule schedule
;
117 u_char
*orig_key
= (u_char
*)keyblock
->keyvalue
.data
;
120 krb5_generate_random_block(r
, 8);
121 md4_update(&md4
, r
, 8);
122 md4_update(&md4
, p
, len
);
123 md4_finito(&md4
, r
+ 8);
124 for (i
= 0; i
< 8; ++i
)
125 key
[i
] = orig_key
[i
] ^ 0xF0;
126 des_set_key(&key
, schedule
);
127 memset (&ivec
, 0, sizeof(ivec
));
128 des_cbc_encrypt(result
, result
, 24, schedule
, &ivec
, DES_ENCRYPT
);
132 MD4_DES_verify (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
137 des_key_schedule schedule
;
140 u_char
*orig_key
= (u_char
*)keyblock
->keyvalue
.data
;
143 for (i
= 0; i
< 8; ++i
)
144 key
[i
] = orig_key
[i
] ^ 0xF0;
145 des_set_key(&key
, schedule
);
146 memset (&ivec
, 0, sizeof(ivec
));
147 des_cbc_encrypt(other
, other
, 24, schedule
, &ivec
, DES_DECRYPT
);
150 md4_update(&md4
, other
, 8);
151 md4_update(&md4
, p
, len
);
152 md4_finito(&md4
, res
);
154 return memcmp (res
, (u_char
*)other
+ 8, 16);
159 MD5_DES_checksum (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
165 des_key_schedule schedule
;
168 u_char
*orig_key
= (u_char
*)keyblock
->keyvalue
.data
;
171 krb5_generate_random_block(r
, 8);
172 md5_update(&md5
, r
, 8);
173 md5_update(&md5
, p
, len
);
174 md5_finito(&md5
, r
+ 8);
175 for (i
= 0; i
< 8; ++i
)
176 key
[i
] = orig_key
[i
] ^ 0xF0;
177 des_set_key(&key
, schedule
);
178 memset (&ivec
, 0, sizeof(ivec
));
179 des_cbc_encrypt(result
, result
, 24, schedule
, &ivec
, DES_ENCRYPT
);
183 MD5_DES_verify (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
188 des_key_schedule schedule
;
191 u_char
*orig_key
= (u_char
*)keyblock
->keyvalue
.data
;
194 for (i
= 0; i
< 8; ++i
)
195 key
[i
] = orig_key
[i
] ^ 0xF0;
196 des_set_key(&key
, schedule
);
197 memset (&ivec
, 0, sizeof(ivec
));
198 des_cbc_encrypt(other
, other
, 24, schedule
, &ivec
, DES_DECRYPT
);
201 md5_update(&md5
, other
, 8);
202 md5_update(&md5
, p
, len
);
203 md5_finito(&md5
, res
);
205 return memcmp (res
, (u_char
*)other
+ 8, 16);
209 fix_des3_key(const krb5_keyblock
*keyblock
, des_key_schedule
*sched
)
211 unsigned char *orig_key
= keyblock
->keyvalue
.data
;
214 for (i
= 0; i
< 8; ++i
){
215 key
[0][i
] = orig_key
[i
] ^ 0xF0;
216 key
[1][i
] = orig_key
[i
+8] ^ 0xF0;
217 key
[2][i
] = orig_key
[i
+16] ^ 0xF0;
219 for(i
= 0; i
< 3; i
++)
220 des_set_key(&key
[i
], sched
[i
]);
221 memset(key
, 0, sizeof(key
));
225 MD5_DES3_checksum (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
230 des_key_schedule sched
[3];
231 unsigned char *r
= result
;
234 krb5_generate_random_block(r
, 8);
235 md5_update(&md5
, r
, 8);
236 md5_update(&md5
, p
, len
);
237 md5_finito(&md5
, r
+ 8);
238 fix_des3_key(keyblock
, sched
);
239 memset (&ivec
, 0, sizeof(ivec
));
240 des_ede3_cbc_encrypt(result
, result
, 24, sched
[0], sched
[1], sched
[2],
242 memset(sched
, 0, sizeof(sched
));
246 MD5_DES3_verify (void *p
, size_t len
, const krb5_keyblock
*keyblock
,
250 des_key_schedule sched
[3];
251 unsigned char res
[16];
254 fix_des3_key(keyblock
, sched
);
255 memset (&ivec
, 0, sizeof(ivec
));
256 des_ede3_cbc_encrypt(other
, other
, 24, sched
[0], sched
[1], sched
[2],
259 memset(sched
, 0, sizeof(sched
));
261 md5_update(&md5
, other
, 8);
262 md5_update(&md5
, p
, len
);
263 md5_finito(&md5
, res
);
265 return memcmp (res
, (unsigned char*)other
+ 8, 16);
269 /* HMAC according to RFC2104 */
271 hmac(struct checksum_type
*cm
, void *data
, size_t len
,
272 const krb5_keyblock
*keyblock
, void *result
)
274 unsigned char *ipad
, *opad
;
275 unsigned char *key
, *tmp_key
= NULL
;
279 key
= keyblock
->keyvalue
.data
;
280 key_len
= keyblock
->keyvalue
.length
;
281 if(key_len
> cm
->blocksize
){
282 tmp_key
= malloc(cm
->checksumsize
);
283 (*cm
->checksum
)(key
, key_len
, keyblock
, tmp_key
);
285 key_len
= cm
->checksumsize
;
287 ipad
= malloc(cm
->blocksize
+ len
);
288 opad
= malloc(cm
->blocksize
+ cm
->checksumsize
);
289 memset(ipad
, 0x36, cm
->blocksize
);
290 memset(opad
, 0x5c, cm
->blocksize
);
291 for(i
= 0; i
< key_len
; i
++){
295 memcpy(ipad
+ cm
->blocksize
, data
, len
);
296 (*cm
->checksum
)(ipad
, cm
->blocksize
+ len
, keyblock
, result
);
297 memcpy(opad
+ cm
->blocksize
, result
, cm
->checksumsize
);
298 (*cm
->checksum
)(opad
, cm
->blocksize
+ cm
->checksumsize
, keyblock
, result
);
305 /* this is used for HMAC-SHA1-DES3, but we make no checks that it
306 actually is a DES3 key that is passed */
308 HMAC_SHA1_checksum(void *data
, size_t len
, const krb5_keyblock
*key
,
311 struct checksum_type
*c
= find_checksum_type(CKSUMTYPE_SHA1
);
312 hmac(c
, data
, len
, key
, result
);
315 static struct checksum_type cm
[] = {
316 { CKSUMTYPE_NONE
, 1, 0, KEYTYPE_NULL
,
317 NULL_checksum
, NULL
, 0, "none" },
318 { CKSUMTYPE_CRC32
, 1, 4, KEYTYPE_NULL
,
319 CRC_checksum
, NULL
, 0, "crc32" },
320 { CKSUMTYPE_RSA_MD4
, 64, 16, KEYTYPE_NULL
,
321 MD4_checksum
, NULL
, F_CPROOF
, "md4" },
322 { CKSUMTYPE_RSA_MD5
, 64, 16, KEYTYPE_NULL
,
323 MD5_checksum
, NULL
, F_CPROOF
, "md5" },
324 { CKSUMTYPE_RSA_MD4_DES
, 64, 24, KEYTYPE_DES
,
325 MD4_DES_checksum
, MD4_DES_verify
, F_KEYED
|F_CPROOF
, "md4-des" },
326 { CKSUMTYPE_RSA_MD5_DES
, 64, 24, KEYTYPE_DES
,
327 MD5_DES_checksum
, MD5_DES_verify
, F_KEYED
|F_CPROOF
, "md5-des" },
328 { CKSUMTYPE_RSA_MD5_DES3
, 64, 24, KEYTYPE_DES3
,
329 MD5_DES3_checksum
, MD5_DES3_verify
, F_KEYED
|F_CPROOF
, "md5-des3" },
330 { CKSUMTYPE_SHA1
, 80, 20, KEYTYPE_NULL
,
331 SHA1_checksum
, NULL
, F_CPROOF
, "sha1" },
332 { CKSUMTYPE_HMAC_SHA1_DES3
, 80, 20, KEYTYPE_DES3
,
333 HMAC_SHA1_checksum
, NULL
, F_KEYED
|F_CPROOF
, "hmac-sha1-des3" }
336 static int num_ctypes
= sizeof(cm
) / sizeof(cm
[0]);
338 static struct checksum_type
*
339 find_checksum_type(krb5_cksumtype ctype
)
341 struct checksum_type
*c
;
342 for(c
= cm
; c
< cm
+ num_ctypes
; c
++)
349 krb5_checksum_is_keyed(krb5_cksumtype ctype
)
351 struct checksum_type
*c
= find_checksum_type(ctype
);
354 return (c
->flags
& F_KEYED
) != 0;
358 krb5_checksum_is_collision_proof(krb5_cksumtype ctype
)
360 struct checksum_type
*c
= find_checksum_type(ctype
);
363 return (c
->flags
& F_CPROOF
) != 0;
367 krb5_checksum_to_string(krb5_context context
, krb5_cksumtype ctype
,
370 struct checksum_type
*c
= find_checksum_type(ctype
);
372 return KRB5_PROG_SUMTYPE_NOSUPP
;
373 *string
= strdup(c
->name
);
378 krb5_string_to_checksum(krb5_context context
, const char *string
,
379 krb5_cksumtype
*ctype
)
382 for(i
= 0; i
< num_ctypes
; i
++)
383 if(strcasecmp(cm
[i
].name
, string
) == 0){
387 return KRB5_PROG_SUMTYPE_NOSUPP
;
391 krb5_cksumsize(krb5_context context
,
395 struct checksum_type
*c
= find_checksum_type(type
);
397 return KRB5_PROG_SUMTYPE_NOSUPP
;
399 *size
= c
->checksumsize
;
404 krb5_create_checksum (krb5_context context
,
408 const krb5_keyblock
*keyblock
,
411 struct checksum_type
*c
;
413 c
= find_checksum_type (type
);
415 return KRB5_PROG_SUMTYPE_NOSUPP
;
416 if (c
->keytype
!= KEYTYPE_NULL
&& c
->keytype
!= keyblock
->keytype
)
417 return KRB5_PROG_KEYTYPE_NOSUPP
;
418 result
->cksumtype
= type
;
419 result
->checksum
.length
= c
->checksumsize
;
420 result
->checksum
.data
= malloc(result
->checksum
.length
);
421 if(result
->checksum
.data
== NULL
)
424 (*c
->checksum
)(ptr
, len
, keyblock
, result
->checksum
.data
);
429 krb5_verify_checksum (krb5_context context
,
432 const krb5_keyblock
*keyblock
,
436 struct checksum_type
*c
;
439 c
= find_checksum_type (cksum
->cksumtype
);
441 return KRB5_PROG_SUMTYPE_NOSUPP
;
442 if (c
->keytype
!= KEYTYPE_NULL
&& c
->keytype
!= keyblock
->keytype
)
443 return KRB5_PROG_KEYTYPE_NOSUPP
;
444 if (cksum
->checksum
.length
!= c
->checksumsize
)
445 return KRB5KRB_AP_ERR_MODIFIED
;
447 ret
= (*c
->verify
)(ptr
, len
, keyblock
, cksum
->checksum
.data
);
449 tmp
= malloc (c
->checksumsize
);
452 (*c
->checksum
)(ptr
, len
, keyblock
, tmp
);
453 ret
= memcmp (cksum
->checksum
.data
, tmp
, c
->checksumsize
);
459 return KRB5KRB_AP_ERR_MODIFIED
;