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 42static int verbose = 0; 43 44static void 45hex_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 54struct { 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 197static int 198string_to_key_test(krb5_context context) 199{ 200 krb5_data password, opaque; 201 krb5_error_code ret; 202 krb5_salt salt; 203 int val = 0; 204 char iter[4]; 205 size_t i; 206 207 for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { 208 209 password.data = keys[i].password; 210 password.length = strlen(password.data); 211 212 salt.salttype = KRB5_PW_SALT; 213 salt.saltvalue.data = keys[i].salt; 214 if (keys[i].saltlen == -1) 215 salt.saltvalue.length = strlen(salt.saltvalue.data); 216 else 217 salt.saltvalue.length = keys[i].saltlen; 218 219 opaque.data = iter; 220 opaque.length = sizeof(iter); 221 _krb5_put_int(iter, keys[i].iterations, 4); 222 223 if (keys[i].pbkdf2) { 224 unsigned char keyout[32]; 225 226 if (keys[i].keylen > sizeof(keyout)) 227 abort(); 228 229 PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, 230 salt.saltvalue.data, salt.saltvalue.length, 231 keys[i].iterations, 232 keys[i].keylen, keyout); 233 234 if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) { 235 krb5_warnx(context, "%d: pbkdf2", (int)i); 236 val = 1; 237 continue; 238 } 239 240 if (verbose) { 241 printf("PBKDF2:\n"); 242 hex_dump_data(keyout, keys[i].keylen); 243 } 244 } 245 246 { 247 krb5_keyblock key; 248 249 ret = krb5_string_to_key_data_salt_opaque (context, 250 keys[i].enctype, 251 password, 252 salt, 253 opaque, 254 &key); 255 if (ret) { 256 krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque", 257 (int)i); 258 val = 1; 259 continue; 260 } 261 262 if (key.keyvalue.length != keys[i].keylen) { 263 krb5_warnx(context, "%d: key wrong length (%lu/%lu)", 264 (int)i, (unsigned long)key.keyvalue.length, 265 (unsigned long)keys[i].keylen); 266 val = 1; 267 continue; 268 } 269 270 if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) { 271 krb5_warnx(context, "%d: key wrong", (int)i); 272 val = 1; 273 continue; 274 } 275 276 if (verbose) { 277 printf("key:\n"); 278 hex_dump_data(key.keyvalue.data, key.keyvalue.length); 279 } 280 krb5_free_keyblock_contents(context, &key); 281 } 282 } 283 return val; 284} 285 286static int 287krb_enc(krb5_context context, 288 krb5_crypto crypto, 289 unsigned usage, 290 krb5_data *cipher, 291 krb5_data *clear) 292{ 293 krb5_data decrypt; 294 krb5_error_code ret; 295 296 krb5_data_zero(&decrypt); 297 298 ret = krb5_decrypt(context, 299 crypto, 300 usage, 301 cipher->data, 302 cipher->length, 303 &decrypt); 304 305 if (ret) { 306 krb5_warn(context, ret, "krb5_decrypt"); 307 return ret; 308 } 309 310 if (decrypt.length != clear->length || 311 memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 312 krb5_warnx(context, "clear text not same"); 313 return EINVAL; 314 } 315 316 krb5_data_free(&decrypt); 317 318 return 0; 319} 320 321static int 322krb_enc_iov2(krb5_context context, 323 krb5_crypto crypto, 324 unsigned usage, 325 size_t cipher_len, 326 krb5_data *clear) 327{ 328 krb5_crypto_iov iov[4]; 329 krb5_data decrypt; 330 int ret; 331 char *p, *q; 332 size_t len, i; 333 334 p = clear->data; 335 len = clear->length; 336 337 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 338 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 339 iov[0].data.data = emalloc(iov[0].data.length); 340 341 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 342 iov[1].data.length = len; 343 iov[1].data.data = emalloc(iov[1].data.length); 344 memcpy(iov[1].data.data, p, iov[1].data.length); 345 346 /* padding buffer */ 347 iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; 348 krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_PADDING, &iov[2].data.length); 349 iov[2].data.data = emalloc(iov[2].data.length); 350 351 iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; 352 krb5_crypto_length(context, crypto, iov[3].flags, &iov[3].data.length); 353 iov[3].data.data = emalloc(iov[3].data.length); 354 355 ret = krb5_encrypt_iov_ivec(context, crypto, usage, 356 iov, sizeof(iov)/sizeof(iov[0]), NULL); 357 if (ret) 358 errx(1, "encrypt iov failed: %d", ret); 359 360 /* check len */ 361 for (i = 0, len = 0; i < sizeof(iov)/sizeof(iov[0]); i++) 362 len += iov[i].data.length; 363 if (len != cipher_len) 364 errx(1, "cipher len wrong"); 365 366 /* 367 * Plain decrypt 368 */ 369 370 p = q = emalloc(len); 371 for (i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 372 memcpy(q, iov[i].data.data, iov[i].data.length); 373 q += iov[i].data.length; 374 } 375 376 ret = krb5_decrypt(context, crypto, usage, p, len, &decrypt); 377 if (ret) 378 krb5_err(context, 1, ret, "krb5_decrypt"); 379 else 380 krb5_data_free(&decrypt); 381 382 free(p); 383 384 /* 385 * Now decrypt use iov 386 */ 387 388 /* padding turn into data */ 389 p = q = emalloc(iov[1].data.length + iov[2].data.length); 390 391 memcpy(q, iov[1].data.data, iov[1].data.length); 392 q += iov[1].data.length; 393 memcpy(q, iov[2].data.data, iov[2].data.length); 394 395 free(iov[1].data.data); 396 free(iov[2].data.data); 397 398 iov[1].data.data = p; 399 iov[1].data.length += iov[2].data.length; 400 401 iov[2].flags = KRB5_CRYPTO_TYPE_EMPTY; 402 iov[2].data.length = 0; 403 404 ret = krb5_decrypt_iov_ivec(context, crypto, usage, 405 iov, sizeof(iov)/sizeof(iov[0]), NULL); 406 free(iov[0].data.data); 407 free(iov[3].data.data); 408 409 if (ret) 410 krb5_err(context, 1, ret, "decrypt iov failed: %d", ret); 411 412 if (clear->length != iov[1].data.length) 413 errx(1, "length incorrect"); 414 415 p = clear->data; 416 if (memcmp(iov[1].data.data, p, iov[1].data.length) != 0) 417 errx(1, "iov[1] incorrect"); 418 419 free(iov[1].data.data); 420 421 return 0; 422} 423 424 425static int 426krb_enc_iov(krb5_context context, 427 krb5_crypto crypto, 428 unsigned usage, 429 krb5_data *cipher, 430 krb5_data *clear) 431{ 432 krb5_crypto_iov iov[3]; 433 int ret; 434 char *p; 435 size_t len; 436 437 p = cipher->data; 438 len = cipher->length; 439 440 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 441 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 442 iov[0].data.data = emalloc(iov[0].data.length); 443 memcpy(iov[0].data.data, p, iov[0].data.length); 444 p += iov[0].data.length; 445 len -= iov[0].data.length; 446 447 iov[1].flags = KRB5_CRYPTO_TYPE_TRAILER; 448 krb5_crypto_length(context, crypto, iov[1].flags, &iov[1].data.length); 449 iov[1].data.data = emalloc(iov[1].data.length); 450 memcpy(iov[1].data.data, p + len - iov[1].data.length, iov[1].data.length); 451 len -= iov[1].data.length; 452 453 iov[2].flags = KRB5_CRYPTO_TYPE_DATA; 454 iov[2].data.length = len; 455 iov[2].data.data = emalloc(len); 456 memcpy(iov[2].data.data, p, len); 457 458 ret = krb5_decrypt_iov_ivec(context, crypto, usage, 459 iov, sizeof(iov)/sizeof(iov[0]), NULL); 460 if (ret) 461 krb5_err(context, 1, ret, "krb_enc_iov decrypt iov failed: %d", ret); 462 463 if (clear->length != iov[2].data.length) 464 errx(1, "length incorrect"); 465 466 p = clear->data; 467 if (memcmp(iov[2].data.data, p, iov[2].data.length) != 0) 468 errx(1, "iov[2] incorrect"); 469 470 free(iov[0].data.data); 471 free(iov[1].data.data); 472 free(iov[2].data.data); 473 474 475 return 0; 476} 477 478static int 479krb_checksum_iov(krb5_context context, 480 krb5_crypto crypto, 481 unsigned usage, 482 krb5_data *plain) 483{ 484 krb5_crypto_iov iov[4]; 485 int ret; 486 char *p; 487 size_t len; 488 489 p = plain->data; 490 len = plain->length; 491 492 iov[0].flags = KRB5_CRYPTO_TYPE_CHECKSUM; 493 krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 494 iov[0].data.data = emalloc(iov[0].data.length); 495 496 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 497 iov[1].data.length = len; 498 iov[1].data.data = p; 499 500 iov[2].flags = KRB5_CRYPTO_TYPE_TRAILER; 501 krb5_crypto_length(context, crypto, iov[0].flags, &iov[2].data.length); 502 iov[2].data.data = malloc(iov[2].data.length); 503 504 ret = krb5_create_checksum_iov(context, crypto, usage, 505 iov, sizeof(iov)/sizeof(iov[0]), NULL); 506 if (ret) 507 krb5_err(context, 1, ret, "krb5_create_checksum_iov failed"); 508 509 ret = krb5_verify_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); 510 if (ret) 511 krb5_err(context, 1, ret, "krb5_verify_checksum_iov"); 512 513 free(iov[0].data.data); 514 free(iov[2].data.data); 515 516 return 0; 517} 518 519 520static int 521krb_enc_mit(krb5_context context, 522 krb5_enctype enctype, 523 krb5_keyblock *key, 524 unsigned usage, 525 krb5_data *cipher, 526 krb5_data *clear) 527{ 528#ifndef HEIMDAL_SMALLER 529 krb5_error_code ret; 530 krb5_enc_data e; 531 krb5_data decrypt; 532 size_t len; 533 534 e.kvno = 0; 535 e.enctype = enctype; 536 e.ciphertext = *cipher; 537 538 ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt); 539 if (ret) 540 return ret; 541 542 if (decrypt.length != clear->length || 543 memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 544 krb5_warnx(context, "clear text not same"); 545 return EINVAL; 546 } 547 548 krb5_data_free(&decrypt); 549 550 ret = krb5_c_encrypt_length(context, enctype, clear->length, &len); 551 if (ret) 552 return ret; 553 554 if (len != cipher->length) { 555 krb5_warnx(context, "c_encrypt_length wrong %lu != %lu", 556 (unsigned long)len, (unsigned long)cipher->length); 557 return EINVAL; 558 } 559#endif /* HEIMDAL_SMALLER */ 560 return 0; 561} 562 563 564struct { 565 krb5_enctype enctype; 566 unsigned usage; 567 size_t keylen; 568 void *key; 569 size_t elen; 570 void* edata; 571 size_t plen; 572 void *pdata; 573} krbencs[] = { 574 { 575 ETYPE_AES256_CTS_HMAC_SHA1_96, 576 7, 577 32, 578 "\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75" 579 "\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65", 580 44, 581 "\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91" 582 "\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24" 583 "\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd", 584 16, 585 "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a" 586 } 587}; 588 589 590static int 591krb_enc_test(krb5_context context) 592{ 593 krb5_error_code ret; 594 krb5_crypto crypto; 595 krb5_keyblock kb; 596 krb5_data cipher, plain; 597 size_t i; 598 599 for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) { 600 601 kb.keytype = krbencs[i].enctype; 602 kb.keyvalue.length = krbencs[i].keylen; 603 kb.keyvalue.data = krbencs[i].key; 604 605 ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto); 606 if (ret) 607 errx(1, "krb5_crypto_init failed with %d for test %d", ret, (int)i); 608 609 cipher.length = krbencs[i].elen; 610 cipher.data = krbencs[i].edata; 611 plain.length = krbencs[i].plen; 612 plain.data = krbencs[i].pdata; 613 614 ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); 615 616 if (ret) 617 errx(1, "krb_enc failed with %d for test %d", ret, (int)i); 618 619 ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain); 620 if (ret) 621 errx(1, "krb_enc_iov failed with %d for test %d", ret, (int)i); 622 623 ret = krb_enc_iov2(context, crypto, krbencs[i].usage, 624 cipher.length, &plain); 625 if (ret) 626 errx(1, "krb_enc_iov2 failed with %d for test %d", ret, (int)i); 627 628 ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain); 629 if (ret) 630 errx(1, "krb_checksum_iov failed with %d for test %d", ret, (int)i); 631 632 krb5_crypto_destroy(context, crypto); 633 634 ret = krb_enc_mit(context, krbencs[i].enctype, &kb, 635 krbencs[i].usage, &cipher, &plain); 636 if (ret) 637 errx(1, "krb_enc_mit failed with %d for test %d", ret, (int)i); 638 } 639 640 return 0; 641} 642 643static int 644iov_test(krb5_context context) 645{ 646 krb5_enctype enctype = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96; 647 krb5_error_code ret; 648 krb5_crypto crypto; 649 krb5_keyblock key; 650 krb5_data signonly, in, in2; 651 krb5_crypto_iov iov[6]; 652 size_t len, i; 653 unsigned char *base, *p; 654 655 ret = krb5_generate_random_keyblock(context, enctype, &key); 656 if (ret) 657 krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); 658 659 ret = krb5_crypto_init(context, &key, 0, &crypto); 660 if (ret) 661 krb5_err(context, 1, ret, "krb5_crypto_init"); 662 663 664 ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len); 665 if (ret) 666 krb5_err(context, 1, ret, "krb5_crypto_length"); 667 668 signonly.data = "This should be signed"; 669 signonly.length = strlen(signonly.data); 670 in.data = "inputdata"; 671 in.length = strlen(in.data); 672 673 in2.data = "INPUTDATA"; 674 in2.length = strlen(in2.data); 675 676 677 memset(iov, 0, sizeof(iov)); 678 679 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 680 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 681 iov[1].data = in; 682 iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 683 iov[2].data = signonly; 684 iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY; 685 iov[4].flags = KRB5_CRYPTO_TYPE_PADDING; 686 iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER; 687 688 ret = krb5_crypto_length_iov(context, crypto, iov, 689 sizeof(iov)/sizeof(iov[0])); 690 if (ret) 691 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 692 693 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 694 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 695 continue; 696 len += iov[i].data.length; 697 } 698 699 base = emalloc(len); 700 701 /* 702 * Allocate data for the fields 703 */ 704 705 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 706 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 707 continue;; 708 iov[i].data.data = p; 709 p += iov[i].data.length; 710 } 711 assert(iov[1].data.length == in.length); 712 memcpy(iov[1].data.data, in.data, iov[1].data.length); 713 714 /* 715 * Encrypt 716 */ 717 718 ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, 719 sizeof(iov)/sizeof(iov[0]), NULL); 720 if (ret) 721 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 722 723 /* 724 * Decrypt 725 */ 726 727 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 728 iov, sizeof(iov)/sizeof(iov[0]), NULL); 729 if (ret) 730 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 731 732 /* 733 * Verify data 734 */ 735 736 if (krb5_data_cmp(&iov[1].data, &in) != 0) 737 krb5_errx(context, 1, "decrypted data not same"); 738 739 /* 740 * Free memory 741 */ 742 743 free(base); 744 745 /* Set up for second try */ 746 747 iov[3].flags = KRB5_CRYPTO_TYPE_DATA; 748 iov[3].data = in; 749 750 ret = krb5_crypto_length_iov(context, crypto, 751 iov, sizeof(iov)/sizeof(iov[0])); 752 if (ret) 753 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 754 755 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 756 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 757 continue; 758 len += iov[i].data.length; 759 } 760 761 base = emalloc(len); 762 763 /* 764 * Allocate data for the fields 765 */ 766 767 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 768 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 769 continue;; 770 iov[i].data.data = p; 771 p += iov[i].data.length; 772 } 773 assert(iov[1].data.length == in.length); 774 memcpy(iov[1].data.data, in.data, iov[1].data.length); 775 776 assert(iov[3].data.length == in2.length); 777 memcpy(iov[3].data.data, in2.data, iov[3].data.length); 778 779 780 781 /* 782 * Encrypt 783 */ 784 785 ret = krb5_encrypt_iov_ivec(context, crypto, 7, 786 iov, sizeof(iov)/sizeof(iov[0]), NULL); 787 if (ret) 788 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 789 790 /* 791 * Decrypt 792 */ 793 794 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 795 iov, sizeof(iov)/sizeof(iov[0]), NULL); 796 if (ret) 797 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 798 799 /* 800 * Verify data 801 */ 802 803 if (krb5_data_cmp(&iov[1].data, &in) != 0) 804 krb5_errx(context, 1, "decrypted data 2.1 not same"); 805 806 if (krb5_data_cmp(&iov[3].data, &in2) != 0) 807 krb5_errx(context, 1, "decrypted data 2.2 not same"); 808 809 /* 810 * Free memory 811 */ 812 813 free(base); 814 815 krb5_crypto_destroy(context, crypto); 816 817 krb5_free_keyblock_contents(context, &key); 818 819 return 0; 820} 821 822 823 824static int 825random_to_key(krb5_context context) 826{ 827 krb5_error_code ret; 828 krb5_keyblock key; 829 830 ret = krb5_random_to_key(context, 831 ETYPE_DES3_CBC_SHA1, 832 "\x21\x39\x04\x58\x6A\xBD\x7F" 833 "\x21\x39\x04\x58\x6A\xBD\x7F" 834 "\x21\x39\x04\x58\x6A\xBD\x7F", 835 21, 836 &key); 837 if (ret){ 838 krb5_warn(context, ret, "random_to_key"); 839 return 1; 840 } 841 if (key.keyvalue.length != 24) 842 return 1; 843 844 if (memcmp(key.keyvalue.data, 845 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 846 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 847 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", 848 24) != 0) 849 return 1; 850 851 krb5_free_keyblock_contents(context, &key); 852 853 return 0; 854} 855 856int 857main(int argc, char **argv) 858{ 859 krb5_error_code ret; 860 krb5_context context; 861 int ival, val = 0; 862 863 ret = krb5_init_context (&context); 864 if (ret) 865 errx (1, "krb5_init_context failed: %d", ret); 866 867 val |= ival = string_to_key_test(context); 868 if (ival && verbose) 869 printf("string to key failed\n"); 870 871 val |= ival = krb_enc_test(context); 872 if (ival && verbose) 873 printf("enc tests failed\n"); 874 875 val |= ival = random_to_key(context); 876 if (ival && verbose) 877 printf("random to key failed\n"); 878 879 val |= ival = iov_test(context); 880 if (ival && verbose) 881 printf("iov test failed\n"); 882 883 if (verbose && val == 0) 884 printf("all ok\n"); 885 if (val) 886 printf("tests failed\n"); 887 888 krb5_free_context(context); 889 890 return val; 891} 892