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 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 285static int 286krb_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 320static int 321krb_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 424static int 425krb_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 477static int 478krb_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 519static int 520krb_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 563struct { 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 589static int 590krb_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 if (ret) 606 errx(1, "krb5_crypto_init failed with %d for test %d", ret, i); 607 608 cipher.length = krbencs[i].elen; 609 cipher.data = krbencs[i].edata; 610 plain.length = krbencs[i].plen; 611 plain.data = krbencs[i].pdata; 612 613 ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); 614 615 if (ret) 616 errx(1, "krb_enc failed with %d for test %d", ret, i); 617 618 ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain); 619 if (ret) 620 errx(1, "krb_enc_iov failed with %d for test %d", ret, i); 621 622 ret = krb_enc_iov2(context, crypto, krbencs[i].usage, 623 cipher.length, &plain); 624 if (ret) 625 errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i); 626 627 ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain); 628 if (ret) 629 errx(1, "krb_checksum_iov failed with %d for test %d", ret, i); 630 631 krb5_crypto_destroy(context, crypto); 632 633 ret = krb_enc_mit(context, krbencs[i].enctype, &kb, 634 krbencs[i].usage, &cipher, &plain); 635 if (ret) 636 errx(1, "krb_enc_mit failed with %d for test %d", ret, i); 637 } 638 639 return 0; 640} 641 642static int 643iov_test(krb5_context context) 644{ 645 krb5_enctype enctype = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96; 646 krb5_error_code ret; 647 krb5_crypto crypto; 648 krb5_keyblock key; 649 krb5_data signonly, in, in2; 650 krb5_crypto_iov iov[6]; 651 size_t len, i; 652 unsigned char *base, *p; 653 654 ret = krb5_generate_random_keyblock(context, enctype, &key); 655 if (ret) 656 krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); 657 658 ret = krb5_crypto_init(context, &key, 0, &crypto); 659 if (ret) 660 krb5_err(context, 1, ret, "krb5_crypto_init"); 661 662 663 ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len); 664 if (ret) 665 krb5_err(context, 1, ret, "krb5_crypto_length"); 666 667 signonly.data = "This should be signed"; 668 signonly.length = strlen(signonly.data); 669 in.data = "inputdata"; 670 in.length = strlen(in.data); 671 672 in2.data = "INPUTDATA"; 673 in2.length = strlen(in2.data); 674 675 676 memset(iov, 0, sizeof(iov)); 677 678 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 679 iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 680 iov[1].data = in; 681 iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 682 iov[2].data = signonly; 683 iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY; 684 iov[4].flags = KRB5_CRYPTO_TYPE_PADDING; 685 iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER; 686 687 ret = krb5_crypto_length_iov(context, crypto, iov, 688 sizeof(iov)/sizeof(iov[0])); 689 if (ret) 690 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 691 692 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 693 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 694 continue; 695 len += iov[i].data.length; 696 } 697 698 base = emalloc(len); 699 700 /* 701 * Allocate data for the fields 702 */ 703 704 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 705 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 706 continue;; 707 iov[i].data.data = p; 708 p += iov[i].data.length; 709 } 710 assert(iov[1].data.length == in.length); 711 memcpy(iov[1].data.data, in.data, iov[1].data.length); 712 713 /* 714 * Encrypt 715 */ 716 717 ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, 718 sizeof(iov)/sizeof(iov[0]), NULL); 719 if (ret) 720 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 721 722 /* 723 * Decrypt 724 */ 725 726 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 727 iov, sizeof(iov)/sizeof(iov[0]), NULL); 728 if (ret) 729 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 730 731 /* 732 * Verify data 733 */ 734 735 if (krb5_data_cmp(&iov[1].data, &in) != 0) 736 krb5_errx(context, 1, "decrypted data not same"); 737 738 /* 739 * Free memory 740 */ 741 742 free(base); 743 744 /* Set up for second try */ 745 746 iov[3].flags = KRB5_CRYPTO_TYPE_DATA; 747 iov[3].data = in; 748 749 ret = krb5_crypto_length_iov(context, crypto, 750 iov, sizeof(iov)/sizeof(iov[0])); 751 if (ret) 752 krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 753 754 for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 755 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 756 continue; 757 len += iov[i].data.length; 758 } 759 760 base = emalloc(len); 761 762 /* 763 * Allocate data for the fields 764 */ 765 766 for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 767 if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 768 continue;; 769 iov[i].data.data = p; 770 p += iov[i].data.length; 771 } 772 assert(iov[1].data.length == in.length); 773 memcpy(iov[1].data.data, in.data, iov[1].data.length); 774 775 assert(iov[3].data.length == in2.length); 776 memcpy(iov[3].data.data, in2.data, iov[3].data.length); 777 778 779 780 /* 781 * Encrypt 782 */ 783 784 ret = krb5_encrypt_iov_ivec(context, crypto, 7, 785 iov, sizeof(iov)/sizeof(iov[0]), NULL); 786 if (ret) 787 krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 788 789 /* 790 * Decrypt 791 */ 792 793 ret = krb5_decrypt_iov_ivec(context, crypto, 7, 794 iov, sizeof(iov)/sizeof(iov[0]), NULL); 795 if (ret) 796 krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 797 798 /* 799 * Verify data 800 */ 801 802 if (krb5_data_cmp(&iov[1].data, &in) != 0) 803 krb5_errx(context, 1, "decrypted data 2.1 not same"); 804 805 if (krb5_data_cmp(&iov[3].data, &in2) != 0) 806 krb5_errx(context, 1, "decrypted data 2.2 not same"); 807 808 /* 809 * Free memory 810 */ 811 812 free(base); 813 814 krb5_crypto_destroy(context, crypto); 815 816 krb5_free_keyblock_contents(context, &key); 817 818 return 0; 819} 820 821 822 823static int 824random_to_key(krb5_context context) 825{ 826 krb5_error_code ret; 827 krb5_keyblock key; 828 829 ret = krb5_random_to_key(context, 830 ETYPE_DES3_CBC_SHA1, 831 "\x21\x39\x04\x58\x6A\xBD\x7F" 832 "\x21\x39\x04\x58\x6A\xBD\x7F" 833 "\x21\x39\x04\x58\x6A\xBD\x7F", 834 21, 835 &key); 836 if (ret){ 837 krb5_warn(context, ret, "random_to_key"); 838 return 1; 839 } 840 if (key.keyvalue.length != 24) 841 return 1; 842 843 if (memcmp(key.keyvalue.data, 844 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 845 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 846 "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", 847 24) != 0) 848 return 1; 849 850 krb5_free_keyblock_contents(context, &key); 851 852 return 0; 853} 854 855int 856main(int argc, char **argv) 857{ 858 krb5_error_code ret; 859 krb5_context context; 860 int ival, val = 0; 861 862 ret = krb5_init_context (&context); 863 if (ret) 864 errx (1, "krb5_init_context failed: %d", ret); 865 866 val |= ival = string_to_key_test(context); 867 if (ival && verbose) 868 printf("string to key failed\n"); 869 870 val |= ival = krb_enc_test(context); 871 if (ival && verbose) 872 printf("enc tests failed\n"); 873 874 val |= ival = random_to_key(context); 875 if (ival && verbose) 876 printf("random to key failed\n"); 877 878 val |= ival = iov_test(context); 879 if (ival && verbose) 880 printf("iov test failed\n"); 881 882 if (verbose && val == 0) 883 printf("all ok\n"); 884 if (val) 885 printf("tests failed\n"); 886 887 krb5_free_context(context); 888 889 return val; 890} 891