1 /* 2 * Copyright (c) 2003 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 16 * 17 * 3. Neither the name of KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 32 33 #include "krb5_locl.h" 34 #include <hex.h> 35 #include <err.h> 36 #include <assert.h> 37 38 #ifdef HAVE_OPENSSL 39 #include <openssl/evp.h> 40 #endif 41 42 static int verbose = 0; 43 44 static void 45 hex_dump_data(const void *data, size_t length) 46 { 47 char *p; 48 49 hex_encode(data, length, &p); 50 printf("%s\n", p); 51 free(p); 52 } 53 54 struct { 55 char *password; 56 char *salt; 57 int saltlen; 58 int iterations; 59 krb5_enctype enctype; 60 size_t keylen; 61 char *pbkdf2; 62 char *key; 63 } keys[] = { 64 { 65 "password", "ATHENA.MIT.EDUraeburn", -1, 66 1, 67 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 68 "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15", 69 "\x42\x26\x3c\x6e\x89\xf4\xfc\x28\xb8\xdf\x68\xee\x09\x79\x9f\x15" 70 }, 71 { 72 "password", "ATHENA.MIT.EDUraeburn", -1, 73 1, 74 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 75 "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15" 76 "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 77 "\xfe\x69\x7b\x52\xbc\x0d\x3c\xe1\x44\x32\xba\x03\x6a\x92\xe6\x5b" 78 "\xbb\x52\x28\x09\x90\xa2\xfa\x27\x88\x39\x98\xd7\x2a\xf3\x01\x61" 79 }, 80 { 81 "password", "ATHENA.MIT.EDUraeburn", -1, 82 2, 83 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 84 "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d", 85 "\xc6\x51\xbf\x29\xe2\x30\x0a\xc2\x7f\xa4\x69\xd6\x93\xbd\xda\x13" 86 }, 87 { 88 "password", "ATHENA.MIT.EDUraeburn", -1, 89 2, 90 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 91 "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d" 92 "\xa0\x53\x78\xb9\x32\x44\xec\x8f\x48\xa9\x9e\x61\xad\x79\x9d\x86", 93 "\xa2\xe1\x6d\x16\xb3\x60\x69\xc1\x35\xd5\xe9\xd2\xe2\x5f\x89\x61" 94 "\x02\x68\x56\x18\xb9\x59\x14\xb4\x67\xc6\x76\x22\x22\x58\x24\xff" 95 }, 96 { 97 "password", "ATHENA.MIT.EDUraeburn", -1, 98 1200, 99 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 100 "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b", 101 "\x4c\x01\xcd\x46\xd6\x32\xd0\x1e\x6d\xbe\x23\x0a\x01\xed\x64\x2a" 102 }, 103 { 104 "password", "ATHENA.MIT.EDUraeburn", -1, 105 1200, 106 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 107 "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b" 108 "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 109 "\x55\xa6\xac\x74\x0a\xd1\x7b\x48\x46\x94\x10\x51\xe1\xe8\xb0\xa7" 110 "\x54\x8d\x93\xb0\xab\x30\xa8\xbc\x3f\xf1\x62\x80\x38\x2b\x8c\x2a" 111 }, 112 { 113 "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, 114 5, 115 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 116 "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49", 117 "\xe9\xb2\x3d\x52\x27\x37\x47\xdd\x5c\x35\xcb\x55\xbe\x61\x9d\x8e" 118 }, 119 { 120 "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, 121 5, 122 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 123 "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49" 124 "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 125 "\x97\xa4\xe7\x86\xbe\x20\xd8\x1a\x38\x2d\x5e\xbc\x96\xd5\x90\x9c" 126 "\xab\xcd\xad\xc8\x7c\xa4\x8f\x57\x45\x04\x15\x9f\x16\xc3\x6e\x31" 127 }, 128 { 129 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 130 "pass phrase equals block size", -1, 131 1200, 132 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 133 "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9", 134 "\x59\xd1\xbb\x78\x9a\x82\x8b\x1a\xa5\x4e\xf9\xc2\x88\x3f\x69\xed" 135 }, 136 { 137 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 138 "pass phrase equals block size", -1, 139 1200, 140 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 141 "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9" 142 "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 143 "\x89\xad\xee\x36\x08\xdb\x8b\xc7\x1f\x1b\xfb\xfe\x45\x94\x86\xb0" 144 "\x56\x18\xb7\x0c\xba\xe2\x20\x92\x53\x4e\x56\xc5\x53\xba\x4b\x34" 145 }, 146 { 147 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 148 "pass phrase exceeds block size", -1, 149 1200, 150 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 151 "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61", 152 "\xcb\x80\x05\xdc\x5f\x90\x17\x9a\x7f\x02\x10\x4c\x00\x18\x75\x1d" 153 }, 154 { 155 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 156 "pass phrase exceeds block size", -1, 157 1200, 158 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 159 "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61" 160 "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 161 "\xd7\x8c\x5c\x9c\xb8\x72\xa8\xc9\xda\xd4\x69\x7f\x0b\xb5\xb2\xd2" 162 "\x14\x96\xc8\x2b\xeb\x2c\xae\xda\x21\x12\xfc\xee\xa0\x57\x40\x1b" 163 164 }, 165 { 166 "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, 167 50, 168 ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 169 "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39", 170 "\xf1\x49\xc1\xf2\xe1\x54\xa7\x34\x52\xd4\x3e\x7f\xe6\x2a\x56\xe5" 171 }, 172 { 173 "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, 174 50, 175 ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 176 "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39" 177 "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2\x81\xff\x30\x69\xe1\xe9\x4f\x52", 178 "\x4b\x6d\x98\x39\xf8\x44\x06\xdf\x1f\x09\xcc\x16\x6d\xb4\xb8\x3c" 179 "\x57\x18\x48\xb7\x84\xa3\xd6\xbd\xc3\x46\x58\x9a\x3e\x39\x3f\x9e" 180 }, 181 { 182 "foo", "", -1, 183 0, 184 ETYPE_ARCFOUR_HMAC_MD5, 16, 185 NULL, 186 "\xac\x8e\x65\x7f\x83\xdf\x82\xbe\xea\x5d\x43\xbd\xaf\x78\x00\xcc" 187 }, 188 { 189 "test", "", -1, 190 0, 191 ETYPE_ARCFOUR_HMAC_MD5, 16, 192 NULL, 193 "\x0c\xb6\x94\x88\x05\xf7\x97\xbf\x2a\x82\x80\x79\x73\xb8\x95\x37" 194 } 195 }; 196 197 static int 198 string_to_key_test(krb5_context context) 199 { 200 krb5_data password, opaque; 201 krb5_error_code ret; 202 krb5_salt salt; 203 int i, val = 0; 204 char iter[4]; 205 206 for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { 207 208 password.data = keys[i].password; 209 password.length = strlen(password.data); 210 211 salt.salttype = KRB5_PW_SALT; 212 salt.saltvalue.data = keys[i].salt; 213 if (keys[i].saltlen == -1) 214 salt.saltvalue.length = strlen(salt.saltvalue.data); 215 else 216 salt.saltvalue.length = keys[i].saltlen; 217 218 opaque.data = iter; 219 opaque.length = sizeof(iter); 220 _krb5_put_int(iter, keys[i].iterations, 4); 221 222 if (keys[i].pbkdf2) { 223 unsigned char keyout[32]; 224 225 if (keys[i].keylen > sizeof(keyout)) 226 abort(); 227 228 PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, 229 salt.saltvalue.data, salt.saltvalue.length, 230 keys[i].iterations, 231 keys[i].keylen, keyout); 232 233 if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) { 234 krb5_warnx(context, "%d: pbkdf2", i); 235 val = 1; 236 continue; 237 } 238 239 if (verbose) { 240 printf("PBKDF2:\n"); 241 hex_dump_data(keyout, keys[i].keylen); 242 } 243 } 244 245 { 246 krb5_keyblock key; 247 248 ret = krb5_string_to_key_data_salt_opaque (context, 249 keys[i].enctype, 250 password, 251 salt, 252 opaque, 253 &key); 254 if (ret) { 255 krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque", 256 i); 257 val = 1; 258 continue; 259 } 260 261 if (key.keyvalue.length != keys[i].keylen) { 262 krb5_warnx(context, "%d: key wrong length (%lu/%lu)", 263 i, (unsigned long)key.keyvalue.length, 264 (unsigned long)keys[i].keylen); 265 val = 1; 266 continue; 267 } 268 269 if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) { 270 krb5_warnx(context, "%d: key wrong", i); 271 val = 1; 272 continue; 273 } 274 275 if (verbose) { 276 printf("key:\n"); 277 hex_dump_data(key.keyvalue.data, key.keyvalue.length); 278 } 279 krb5_free_keyblock_contents(context, &key); 280 } 281 } 282 return val; 283 } 284 285 static int 286 krb_enc(krb5_context context, 287 krb5_crypto crypto, 288 unsigned usage, 289 krb5_data *cipher, 290 krb5_data *clear) 291 { 292 krb5_data decrypt; 293 krb5_error_code ret; 294 295 krb5_data_zero(&decrypt); 296 297 ret = krb5_decrypt(context, 298 crypto, 299 usage, 300 cipher->data, 301 cipher->length, 302 &decrypt); 303 304 if (ret) { 305 krb5_warn(context, ret, "krb5_decrypt"); 306 return ret; 307 } 308 309 if (decrypt.length != clear->length || 310 memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 311 krb5_warnx(context, "clear text not same"); 312 return EINVAL; 313 } 314 315 krb5_data_free(&decrypt); 316 317 return 0; 318 } 319 320 static int 321 krb_enc_iov2(krb5_context context, 322 krb5_crypto crypto, 323 unsigned usage, 324 size_t cipher_len, 325 krb5_data *clear) 326 { 327 krb5_crypto_iov iov[4]; 328 krb5_data decrypt; 329 int ret; 330 char *p, *q; 331 size_t len, i; 332 333 p = clear->data; 334 len = clear->length; 335 336 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 337 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 338 iov[0].data.data = emalloc(iov[0].data.length); 339 340 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 341 iov[1].data.length = len; 342 iov[1].data.data = emalloc(iov[1].data.length); 343 memcpy(iov[1].data.data, p, iov[1].data.length); 344 345 /* padding buffer */ 346 iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; 347 krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_PADDING, &iov[2].data.length); 348 iov[2].data.data = emalloc(iov[2].data.length); 349 350 iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; 351 krb5_crypto_length(context, crypto, iov[3].flags, &iov[3].data.length); 352 iov[3].data.data = emalloc(iov[3].data.length); 353 354 ret = krb5_encrypt_iov_ivec(context, crypto, usage, 355 iov, sizeof(iov)/sizeof(iov[0]), NULL); 356 if (ret) 357 errx(1, "encrypt iov failed: %d", ret); 358 359 /* check len */ 360 for (i = 0, len = 0; i < sizeof(iov)/sizeof(iov[0]); i++) 361 len += iov[i].data.length; 362 if (len != cipher_len) 363 errx(1, "cipher len wrong"); 364 365 /* 366 * Plain decrypt 367 */ 368 369 p = q = emalloc(len); 370 for (i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 371 memcpy(q, iov[i].data.data, iov[i].data.length); 372 q += iov[i].data.length; 373 } 374 375 ret = krb5_decrypt(context, crypto, usage, p, len, &decrypt); 376 if (ret) 377 krb5_err(context, 1, ret, "krb5_decrypt"); 378 else 379 krb5_data_free(&decrypt); 380 381 free(p); 382 383 /* 384 * Now decrypt use iov 385 */ 386 387 /* padding turn into data */ 388 p = q = emalloc(iov[1].data.length + iov[2].data.length); 389 390 memcpy(q, iov[1].data.data, iov[1].data.length); 391 q += iov[1].data.length; 392 memcpy(q, iov[2].data.data, iov[2].data.length); 393 394 free(iov[1].data.data); 395 free(iov[2].data.data); 396 397 iov[1].data.data = p; 398 iov[1].data.length += iov[2].data.length; 399 400 iov[2].flags = KRB5_CRYPTO_TYPE_EMPTY; 401 iov[2].data.length = 0; 402 403 ret = krb5_decrypt_iov_ivec(context, crypto, usage, 404 iov, sizeof(iov)/sizeof(iov[0]), NULL); 405 free(iov[0].data.data); 406 free(iov[3].data.data); 407 408 if (ret) 409 krb5_err(context, 1, ret, "decrypt iov failed: %d", ret); 410 411 if (clear->length != iov[1].data.length) 412 errx(1, "length incorrect"); 413 414 p = clear->data; 415 if (memcmp(iov[1].data.data, p, iov[1].data.length) != 0) 416 errx(1, "iov[1] incorrect"); 417 418 free(iov[1].data.data); 419 420 return 0; 421 } 422 423 424 static int 425 krb_enc_iov(krb5_context context, 426 krb5_crypto crypto, 427 unsigned usage, 428 krb5_data *cipher, 429 krb5_data *clear) 430 { 431 krb5_crypto_iov iov[3]; 432 int ret; 433 char *p; 434 size_t len; 435 436 p = cipher->data; 437 len = cipher->length; 438 439 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 440 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 441 iov[0].data.data = emalloc(iov[0].data.length); 442 memcpy(iov[0].data.data, p, iov[0].data.length); 443 p += iov[0].data.length; 444 len -= iov[0].data.length; 445 446 iov[1].flags = KRB5_CRYPTO_TYPE_TRAILER; 447 krb5_crypto_length(context, crypto, iov[1].flags, &iov[1].data.length); 448 iov[1].data.data = emalloc(iov[1].data.length); 449 memcpy(iov[1].data.data, p + len - iov[1].data.length, iov[1].data.length); 450 len -= iov[1].data.length; 451 452 iov[2].flags = KRB5_CRYPTO_TYPE_DATA; 453 iov[2].data.length = len; 454 iov[2].data.data = emalloc(len); 455 memcpy(iov[2].data.data, p, len); 456 457 ret = krb5_decrypt_iov_ivec(context, crypto, usage, 458 iov, sizeof(iov)/sizeof(iov[0]), NULL); 459 if (ret) 460 krb5_err(context, 1, ret, "krb_enc_iov decrypt iov failed: %d", ret); 461 462 if (clear->length != iov[2].data.length) 463 errx(1, "length incorrect"); 464 465 p = clear->data; 466 if (memcmp(iov[2].data.data, p, iov[2].data.length) != 0) 467 errx(1, "iov[2] incorrect"); 468 469 free(iov[0].data.data); 470 free(iov[1].data.data); 471 free(iov[2].data.data); 472 473 474 return 0; 475 } 476 477 static int 478 krb_checksum_iov(krb5_context context, 479 krb5_crypto crypto, 480 unsigned usage, 481 krb5_data *plain) 482 { 483 krb5_crypto_iov iov[4]; 484 int ret; 485 char *p; 486 size_t len; 487 488 p = plain->data; 489 len = plain->length; 490 491 iov[0].flags = KRB5_CRYPTO_TYPE_CHECKSUM; 492 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 493 iov[0].data.data = emalloc(iov[0].data.length); 494 495 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 496 iov[1].data.length = len; 497 iov[1].data.data = p; 498 499 iov[2].flags = KRB5_CRYPTO_TYPE_TRAILER; 500 krb5_crypto_length(context, crypto, iov[0].flags, &iov[2].data.length); 501 iov[2].data.data = malloc(iov[2].data.length); 502 503 ret = krb5_create_checksum_iov(context, crypto, usage, 504 iov, sizeof(iov)/sizeof(iov[0]), NULL); 505 if (ret) 506 krb5_err(context, 1, ret, "krb5_create_checksum_iov failed"); 507 508 ret = krb5_verify_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); 509 if (ret) 510 krb5_err(context, 1, ret, "krb5_verify_checksum_iov"); 511 512 free(iov[0].data.data); 513 free(iov[2].data.data); 514 515 return 0; 516 } 517 518 519 static int 520 krb_enc_mit(krb5_context context, 521 krb5_enctype enctype, 522 krb5_keyblock *key, 523 unsigned usage, 524 krb5_data *cipher, 525 krb5_data *clear) 526 { 527 #ifndef HEIMDAL_SMALLER 528 krb5_error_code ret; 529 krb5_enc_data e; 530 krb5_data decrypt; 531 size_t len; 532 533 e.kvno = 0; 534 e.enctype = enctype; 535 e.ciphertext = *cipher; 536 537 ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt); 538 if (ret) 539 return ret; 540 541 if (decrypt.length != clear->length || 542 memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 543 krb5_warnx(context, "clear text not same"); 544 return EINVAL; 545 } 546 547 krb5_data_free(&decrypt); 548 549 ret = krb5_c_encrypt_length(context, enctype, clear->length, &len); 550 if (ret) 551 return ret; 552 553 if (len != cipher->length) { 554 krb5_warnx(context, "c_encrypt_length wrong %lu != %lu", 555 (unsigned long)len, (unsigned long)cipher->length); 556 return EINVAL; 557 } 558 #endif /* HEIMDAL_SMALLER */ 559 return 0; 560 } 561 562 563 struct { 564 krb5_enctype enctype; 565 unsigned usage; 566 size_t keylen; 567 void *key; 568 size_t elen; 569 void* edata; 570 size_t plen; 571 void *pdata; 572 } krbencs[] = { 573 { 574 ETYPE_AES256_CTS_HMAC_SHA1_96, 575 7, 576 32, 577 "\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75" 578 "\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65", 579 44, 580 "\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91" 581 "\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24" 582 "\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd", 583 16, 584 "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a" 585 } 586 }; 587 588 589 static int 590 krb_enc_test(krb5_context context) 591 { 592 krb5_error_code ret; 593 krb5_crypto crypto; 594 krb5_keyblock kb; 595 krb5_data cipher, plain; 596 int i; 597 598 for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) { 599 600 kb.keytype = krbencs[i].enctype; 601 kb.keyvalue.length = krbencs[i].keylen; 602 kb.keyvalue.data = krbencs[i].key; 603 604 ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto); 605 606 cipher.length = krbencs[i].elen; 607 cipher.data = krbencs[i].edata; 608 plain.length = krbencs[i].plen; 609 plain.data = krbencs[i].pdata; 610 611 ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); 612 613 if (ret) 614 errx(1, "krb_enc failed with %d for test %d", ret, i); 615 616 ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain); 617 if (ret) 618 errx(1, "krb_enc_iov failed with %d for test %d", ret, i); 619 620 ret = krb_enc_iov2(context, crypto, krbencs[i].usage, 621 cipher.length, &plain); 622 if (ret) 623 errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i); 624 625 ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain); 626 if (ret) 627 errx(1, "krb_checksum_iov failed with %d for test %d", ret, i); 628 629 krb5_crypto_destroy(context, crypto); 630 631 ret = krb_enc_mit(context, krbencs[i].enctype, &kb, 632 krbencs[i].usage, &cipher, &plain); 633 if (ret) 634 errx(1, "krb_enc_mit failed with %d for test %d", ret, i); 635 } 636 637 return 0; 638 } 639 640 static int 641 iov_test(krb5_context context) 642 { 643 krb5_enctype enctype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; 644 krb5_error_code ret; 645 krb5_crypto crypto; 646 krb5_keyblock key; 647 krb5_data signonly, in, in2; 648 krb5_crypto_iov iov[6]; 649 size_t len, i; 650 unsigned char *base, *p; 651 652 ret = krb5_generate_random_keyblock(context, enctype, &key); 653 if (ret) 654 krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); 655 656 ret = krb5_crypto_init(context, &key, 0, &crypto); 657 if (ret) 658 krb5_err(context, 1, ret, "krb5_crypto_init"); 659 660 661 ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len); 662 if (ret) 663 krb5_err(context, 1, ret, "krb5_crypto_length"); 664 665 signonly.data = "This should be signed"; 666 signonly.length = strlen(signonly.data); 667 in.data = "inputdata"; 668 in.length = strlen(in.data); 669 670 in2.data = "INPUTDATA"; 671 in2.length = strlen(in2.data); 672 673 674 memset(iov, 0, sizeof(iov)); 675 676 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 677 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 678 iov[1].data = in; 679 iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 680 iov[2].data = signonly; 681 iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY; 682 iov[4].flags = KRB5_CRYPTO_TYPE_PADDING; 683 iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER; 684 685 ret = krb5_crypto_length_iov(context, crypto, iov, 686 sizeof(iov)/sizeof(iov[0])); 687 if (ret) 688 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 689 690 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 691 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 692 continue; 693 len += iov[i].data.length; 694 } 695 696 base = emalloc(len); 697 698 /* 699 * Allocate data for the fields 700 */ 701 702 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 703 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 704 continue;; 705 iov[i].data.data = p; 706 p += iov[i].data.length; 707 } 708 assert(iov[1].data.length == in.length); 709 memcpy(iov[1].data.data, in.data, iov[1].data.length); 710 711 /* 712 * Encrypt 713 */ 714 715 ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, 716 sizeof(iov)/sizeof(iov[0]), NULL); 717 if (ret) 718 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 719 720 /* 721 * Decrypt 722 */ 723 724 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 725 iov, sizeof(iov)/sizeof(iov[0]), NULL); 726 if (ret) 727 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 728 729 /* 730 * Verify data 731 */ 732 733 if (krb5_data_cmp(&iov[1].data, &in) != 0) 734 krb5_errx(context, 1, "decrypted data not same"); 735 736 /* 737 * Free memory 738 */ 739 740 free(base); 741 742 /* Set up for second try */ 743 744 iov[3].flags = KRB5_CRYPTO_TYPE_DATA; 745 iov[3].data = in; 746 747 ret = krb5_crypto_length_iov(context, crypto, 748 iov, sizeof(iov)/sizeof(iov[0])); 749 if (ret) 750 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 751 752 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 753 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 754 continue; 755 len += iov[i].data.length; 756 } 757 758 base = emalloc(len); 759 760 /* 761 * Allocate data for the fields 762 */ 763 764 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 765 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 766 continue;; 767 iov[i].data.data = p; 768 p += iov[i].data.length; 769 } 770 assert(iov[1].data.length == in.length); 771 memcpy(iov[1].data.data, in.data, iov[1].data.length); 772 773 assert(iov[3].data.length == in2.length); 774 memcpy(iov[3].data.data, in2.data, iov[3].data.length); 775 776 777 778 /* 779 * Encrypt 780 */ 781 782 ret = krb5_encrypt_iov_ivec(context, crypto, 7, 783 iov, sizeof(iov)/sizeof(iov[0]), NULL); 784 if (ret) 785 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 786 787 /* 788 * Decrypt 789 */ 790 791 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 792 iov, sizeof(iov)/sizeof(iov[0]), NULL); 793 if (ret) 794 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 795 796 /* 797 * Verify data 798 */ 799 800 if (krb5_data_cmp(&iov[1].data, &in) != 0) 801 krb5_errx(context, 1, "decrypted data 2.1 not same"); 802 803 if (krb5_data_cmp(&iov[3].data, &in2) != 0) 804 krb5_errx(context, 1, "decrypted data 2.2 not same"); 805 806 /* 807 * Free memory 808 */ 809 810 free(base); 811 812 krb5_crypto_destroy(context, crypto); 813 814 krb5_free_keyblock_contents(context, &key); 815 816 return 0; 817 } 818 819 820 821 static int 822 random_to_key(krb5_context context) 823 { 824 krb5_error_code ret; 825 krb5_keyblock key; 826 827 ret = krb5_random_to_key(context, 828 ETYPE_DES3_CBC_SHA1, 829 "\x21\x39\x04\x58\x6A\xBD\x7F" 830 "\x21\x39\x04\x58\x6A\xBD\x7F" 831 "\x21\x39\x04\x58\x6A\xBD\x7F", 832 21, 833 &key); 834 if (ret){ 835 krb5_warn(context, ret, "random_to_key"); 836 return 1; 837 } 838 if (key.keyvalue.length != 24) 839 return 1; 840 841 if (memcmp(key.keyvalue.data, 842 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 843 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 844 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", 845 24) != 0) 846 return 1; 847 848 krb5_free_keyblock_contents(context, &key); 849 850 return 0; 851 } 852 853 int 854 main(int argc, char **argv) 855 { 856 krb5_error_code ret; 857 krb5_context context; 858 int val = 0; 859 860 ret = krb5_init_context (&context); 861 if (ret) 862 errx (1, "krb5_init_context failed: %d", ret); 863 864 val |= string_to_key_test(context); 865 866 val |= krb_enc_test(context); 867 val |= random_to_key(context); 868 val |= iov_test(context); 869 870 if (verbose && val == 0) 871 printf("all ok\n"); 872 if (val) 873 printf("tests failed\n"); 874 875 krb5_free_context(context); 876 877 return val; 878 } 879