1120945Snectar/* 2233294Sstas * Copyright (c) 2003 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5120945Snectar * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9120945Snectar * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12120945Snectar * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16120945Snectar * 17120945Snectar * 3. Neither the name of KTH nor the names of its contributors may be 18120945Snectar * used to endorse or promote products derived from this software without 19120945Snectar * specific prior written permission. 20120945Snectar * 21120945Snectar * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22120945Snectar * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23120945Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24120945Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25120945Snectar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26120945Snectar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27120945Snectar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28120945Snectar * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29120945Snectar * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30120945Snectar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31120945Snectar * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 32120945Snectar 33120945Snectar#include "krb5_locl.h" 34178825Sdfr#include <hex.h> 35178825Sdfr#include <err.h> 36233294Sstas#include <assert.h> 37120945Snectar 38120945Snectar#ifdef HAVE_OPENSSL 39120945Snectar#include <openssl/evp.h> 40120945Snectar#endif 41120945Snectar 42120945Snectarstatic int verbose = 0; 43120945Snectar 44120945Snectarstatic void 45178825Sdfrhex_dump_data(const void *data, size_t length) 46120945Snectar{ 47178825Sdfr char *p; 48120945Snectar 49178825Sdfr hex_encode(data, length, &p); 50178825Sdfr printf("%s\n", p); 51178825Sdfr free(p); 52120945Snectar} 53120945Snectar 54120945Snectarstruct { 55120945Snectar char *password; 56120945Snectar char *salt; 57120945Snectar int saltlen; 58120945Snectar int iterations; 59120945Snectar krb5_enctype enctype; 60178825Sdfr size_t keylen; 61120945Snectar char *pbkdf2; 62120945Snectar char *key; 63120945Snectar} keys[] = { 64233294Sstas { 65120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 66233294Sstas 1, 67120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 68120945Snectar "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15", 69120945Snectar "\x42\x26\x3c\x6e\x89\xf4\xfc\x28\xb8\xdf\x68\xee\x09\x79\x9f\x15" 70120945Snectar }, 71120945Snectar { 72120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 73233294Sstas 1, 74120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 75120945Snectar "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15" 76120945Snectar "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 77120945Snectar "\xfe\x69\x7b\x52\xbc\x0d\x3c\xe1\x44\x32\xba\x03\x6a\x92\xe6\x5b" 78120945Snectar "\xbb\x52\x28\x09\x90\xa2\xfa\x27\x88\x39\x98\xd7\x2a\xf3\x01\x61" 79120945Snectar }, 80120945Snectar { 81120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 82120945Snectar 2, 83120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 84120945Snectar "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d", 85120945Snectar "\xc6\x51\xbf\x29\xe2\x30\x0a\xc2\x7f\xa4\x69\xd6\x93\xbd\xda\x13" 86120945Snectar }, 87120945Snectar { 88120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 89233294Sstas 2, 90120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 91120945Snectar "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d" 92120945Snectar "\xa0\x53\x78\xb9\x32\x44\xec\x8f\x48\xa9\x9e\x61\xad\x79\x9d\x86", 93120945Snectar "\xa2\xe1\x6d\x16\xb3\x60\x69\xc1\x35\xd5\xe9\xd2\xe2\x5f\x89\x61" 94120945Snectar "\x02\x68\x56\x18\xb9\x59\x14\xb4\x67\xc6\x76\x22\x22\x58\x24\xff" 95120945Snectar }, 96120945Snectar { 97120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 98233294Sstas 1200, 99120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 100120945Snectar "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b", 101120945Snectar "\x4c\x01\xcd\x46\xd6\x32\xd0\x1e\x6d\xbe\x23\x0a\x01\xed\x64\x2a" 102120945Snectar }, 103120945Snectar { 104120945Snectar "password", "ATHENA.MIT.EDUraeburn", -1, 105233294Sstas 1200, 106120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 107120945Snectar "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b" 108120945Snectar "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 109120945Snectar "\x55\xa6\xac\x74\x0a\xd1\x7b\x48\x46\x94\x10\x51\xe1\xe8\xb0\xa7" 110120945Snectar "\x54\x8d\x93\xb0\xab\x30\xa8\xbc\x3f\xf1\x62\x80\x38\x2b\x8c\x2a" 111120945Snectar }, 112120945Snectar { 113120945Snectar "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, 114120945Snectar 5, 115120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 116120945Snectar "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49", 117120945Snectar "\xe9\xb2\x3d\x52\x27\x37\x47\xdd\x5c\x35\xcb\x55\xbe\x61\x9d\x8e" 118120945Snectar }, 119120945Snectar { 120120945Snectar "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, 121120945Snectar 5, 122120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 123120945Snectar "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49" 124120945Snectar "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 125120945Snectar "\x97\xa4\xe7\x86\xbe\x20\xd8\x1a\x38\x2d\x5e\xbc\x96\xd5\x90\x9c" 126120945Snectar "\xab\xcd\xad\xc8\x7c\xa4\x8f\x57\x45\x04\x15\x9f\x16\xc3\x6e\x31" 127120945Snectar }, 128120945Snectar { 129120945Snectar "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 130120945Snectar "pass phrase equals block size", -1, 131120945Snectar 1200, 132120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 133120945Snectar "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9", 134120945Snectar "\x59\xd1\xbb\x78\x9a\x82\x8b\x1a\xa5\x4e\xf9\xc2\x88\x3f\x69\xed" 135120945Snectar }, 136120945Snectar { 137120945Snectar "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 138120945Snectar "pass phrase equals block size", -1, 139120945Snectar 1200, 140120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 141120945Snectar "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9" 142120945Snectar "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 143120945Snectar "\x89\xad\xee\x36\x08\xdb\x8b\xc7\x1f\x1b\xfb\xfe\x45\x94\x86\xb0" 144120945Snectar "\x56\x18\xb7\x0c\xba\xe2\x20\x92\x53\x4e\x56\xc5\x53\xba\x4b\x34" 145120945Snectar }, 146120945Snectar { 147120945Snectar "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 148120945Snectar "pass phrase exceeds block size", -1, 149120945Snectar 1200, 150120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 151120945Snectar "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61", 152120945Snectar "\xcb\x80\x05\xdc\x5f\x90\x17\x9a\x7f\x02\x10\x4c\x00\x18\x75\x1d" 153120945Snectar }, 154120945Snectar { 155120945Snectar "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 156120945Snectar "pass phrase exceeds block size", -1, 157120945Snectar 1200, 158120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 159120945Snectar "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61" 160120945Snectar "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 161120945Snectar "\xd7\x8c\x5c\x9c\xb8\x72\xa8\xc9\xda\xd4\x69\x7f\x0b\xb5\xb2\xd2" 162120945Snectar "\x14\x96\xc8\x2b\xeb\x2c\xae\xda\x21\x12\xfc\xee\xa0\x57\x40\x1b" 163120945Snectar 164120945Snectar }, 165120945Snectar { 166120945Snectar "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, 167120945Snectar 50, 168120945Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 16, 169120945Snectar "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39", 170120945Snectar "\xf1\x49\xc1\xf2\xe1\x54\xa7\x34\x52\xd4\x3e\x7f\xe6\x2a\x56\xe5" 171120945Snectar }, 172120945Snectar { 173120945Snectar "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, 174120945Snectar 50, 175120945Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 32, 176120945Snectar "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39" 177120945Snectar "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2\x81\xff\x30\x69\xe1\xe9\x4f\x52", 178120945Snectar "\x4b\x6d\x98\x39\xf8\x44\x06\xdf\x1f\x09\xcc\x16\x6d\xb4\xb8\x3c" 179120945Snectar "\x57\x18\x48\xb7\x84\xa3\xd6\xbd\xc3\x46\x58\x9a\x3e\x39\x3f\x9e" 180120945Snectar }, 181120945Snectar { 182233294Sstas "foo", "", -1, 183120945Snectar 0, 184120945Snectar ETYPE_ARCFOUR_HMAC_MD5, 16, 185120945Snectar NULL, 186120945Snectar "\xac\x8e\x65\x7f\x83\xdf\x82\xbe\xea\x5d\x43\xbd\xaf\x78\x00\xcc" 187120945Snectar }, 188120945Snectar { 189233294Sstas "test", "", -1, 190120945Snectar 0, 191120945Snectar ETYPE_ARCFOUR_HMAC_MD5, 16, 192120945Snectar NULL, 193120945Snectar "\x0c\xb6\x94\x88\x05\xf7\x97\xbf\x2a\x82\x80\x79\x73\xb8\x95\x37" 194120945Snectar } 195120945Snectar}; 196120945Snectar 197120945Snectarstatic int 198120945Snectarstring_to_key_test(krb5_context context) 199120945Snectar{ 200120945Snectar krb5_data password, opaque; 201120945Snectar krb5_error_code ret; 202120945Snectar krb5_salt salt; 203120945Snectar int i, val = 0; 204120945Snectar char iter[4]; 205120945Snectar 206120945Snectar for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { 207120945Snectar 208120945Snectar password.data = keys[i].password; 209120945Snectar password.length = strlen(password.data); 210120945Snectar 211120945Snectar salt.salttype = KRB5_PW_SALT; 212120945Snectar salt.saltvalue.data = keys[i].salt; 213120945Snectar if (keys[i].saltlen == -1) 214120945Snectar salt.saltvalue.length = strlen(salt.saltvalue.data); 215120945Snectar else 216120945Snectar salt.saltvalue.length = keys[i].saltlen; 217233294Sstas 218120945Snectar opaque.data = iter; 219120945Snectar opaque.length = sizeof(iter); 220120945Snectar _krb5_put_int(iter, keys[i].iterations, 4); 221233294Sstas 222178825Sdfr if (keys[i].pbkdf2) { 223178825Sdfr unsigned char keyout[32]; 224120945Snectar 225178825Sdfr if (keys[i].keylen > sizeof(keyout)) 226178825Sdfr abort(); 227120945Snectar 228120945Snectar PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, 229120945Snectar salt.saltvalue.data, salt.saltvalue.length, 230233294Sstas keys[i].iterations, 231120945Snectar keys[i].keylen, keyout); 232233294Sstas 233120945Snectar if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) { 234178825Sdfr krb5_warnx(context, "%d: pbkdf2", i); 235120945Snectar val = 1; 236120945Snectar continue; 237120945Snectar } 238233294Sstas 239178825Sdfr if (verbose) { 240178825Sdfr printf("PBKDF2:\n"); 241178825Sdfr hex_dump_data(keyout, keys[i].keylen); 242178825Sdfr } 243178825Sdfr } 244178825Sdfr 245178825Sdfr { 246178825Sdfr krb5_keyblock key; 247178825Sdfr 248178825Sdfr ret = krb5_string_to_key_data_salt_opaque (context, 249178825Sdfr keys[i].enctype, 250233294Sstas password, 251233294Sstas salt, 252233294Sstas opaque, 253178825Sdfr &key); 254120945Snectar if (ret) { 255233294Sstas krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque", 256178825Sdfr i); 257120945Snectar val = 1; 258120945Snectar continue; 259120945Snectar } 260233294Sstas 261120945Snectar if (key.keyvalue.length != keys[i].keylen) { 262178825Sdfr krb5_warnx(context, "%d: key wrong length (%lu/%lu)", 263233294Sstas i, (unsigned long)key.keyvalue.length, 264178825Sdfr (unsigned long)keys[i].keylen); 265120945Snectar val = 1; 266120945Snectar continue; 267120945Snectar } 268233294Sstas 269178825Sdfr if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) { 270178825Sdfr krb5_warnx(context, "%d: key wrong", i); 271120945Snectar val = 1; 272120945Snectar continue; 273120945Snectar } 274233294Sstas 275120945Snectar if (verbose) { 276178825Sdfr printf("key:\n"); 277178825Sdfr hex_dump_data(key.keyvalue.data, key.keyvalue.length); 278120945Snectar } 279120945Snectar krb5_free_keyblock_contents(context, &key); 280120945Snectar } 281120945Snectar } 282120945Snectar return val; 283120945Snectar} 284120945Snectar 285233294Sstasstatic int 286233294Sstaskrb_enc(krb5_context context, 287233294Sstas krb5_crypto crypto, 288233294Sstas unsigned usage, 289233294Sstas krb5_data *cipher, 290233294Sstas krb5_data *clear) 291233294Sstas{ 292233294Sstas krb5_data decrypt; 293233294Sstas krb5_error_code ret; 294178825Sdfr 295233294Sstas krb5_data_zero(&decrypt); 296233294Sstas 297233294Sstas ret = krb5_decrypt(context, 298233294Sstas crypto, 299233294Sstas usage, 300233294Sstas cipher->data, 301233294Sstas cipher->length, 302233294Sstas &decrypt); 303233294Sstas 304233294Sstas if (ret) { 305233294Sstas krb5_warn(context, ret, "krb5_decrypt"); 306233294Sstas return ret; 307120945Snectar } 308178825Sdfr 309233294Sstas if (decrypt.length != clear->length || 310233294Sstas memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 311233294Sstas krb5_warnx(context, "clear text not same"); 312233294Sstas return EINVAL; 313178825Sdfr } 314178825Sdfr 315233294Sstas krb5_data_free(&decrypt); 316178825Sdfr 317233294Sstas return 0; 318233294Sstas} 319178825Sdfr 320233294Sstasstatic int 321233294Sstaskrb_enc_iov2(krb5_context context, 322233294Sstas krb5_crypto crypto, 323233294Sstas unsigned usage, 324233294Sstas size_t cipher_len, 325233294Sstas krb5_data *clear) 326233294Sstas{ 327233294Sstas krb5_crypto_iov iov[4]; 328233294Sstas krb5_data decrypt; 329233294Sstas int ret; 330233294Sstas char *p, *q; 331233294Sstas size_t len, i; 332120945Snectar 333233294Sstas p = clear->data; 334233294Sstas len = clear->length; 335178825Sdfr 336233294Sstas iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 337233294Sstas krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 338233294Sstas iov[0].data.data = emalloc(iov[0].data.length); 339178825Sdfr 340233294Sstas iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 341233294Sstas iov[1].data.length = len; 342233294Sstas iov[1].data.data = emalloc(iov[1].data.length); 343233294Sstas memcpy(iov[1].data.data, p, iov[1].data.length); 344120945Snectar 345233294Sstas /* padding buffer */ 346233294Sstas iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; 347233294Sstas krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_PADDING, &iov[2].data.length); 348233294Sstas iov[2].data.data = emalloc(iov[2].data.length); 349233294Sstas 350233294Sstas iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; 351233294Sstas krb5_crypto_length(context, crypto, iov[3].flags, &iov[3].data.length); 352233294Sstas iov[3].data.data = emalloc(iov[3].data.length); 353233294Sstas 354233294Sstas ret = krb5_encrypt_iov_ivec(context, crypto, usage, 355233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 356233294Sstas if (ret) 357233294Sstas errx(1, "encrypt iov failed: %d", ret); 358233294Sstas 359233294Sstas /* check len */ 360233294Sstas for (i = 0, len = 0; i < sizeof(iov)/sizeof(iov[0]); i++) 361233294Sstas len += iov[i].data.length; 362233294Sstas if (len != cipher_len) 363233294Sstas errx(1, "cipher len wrong"); 364233294Sstas 365233294Sstas /* 366233294Sstas * Plain decrypt 367233294Sstas */ 368233294Sstas 369233294Sstas p = q = emalloc(len); 370233294Sstas for (i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 371233294Sstas memcpy(q, iov[i].data.data, iov[i].data.length); 372233294Sstas q += iov[i].data.length; 373120945Snectar } 374120945Snectar 375233294Sstas ret = krb5_decrypt(context, crypto, usage, p, len, &decrypt); 376233294Sstas if (ret) 377233294Sstas krb5_err(context, 1, ret, "krb5_decrypt"); 378233294Sstas else 379233294Sstas krb5_data_free(&decrypt); 380120945Snectar 381233294Sstas free(p); 382120945Snectar 383233294Sstas /* 384233294Sstas * Now decrypt use iov 385233294Sstas */ 386178825Sdfr 387233294Sstas /* padding turn into data */ 388233294Sstas p = q = emalloc(iov[1].data.length + iov[2].data.length); 389120945Snectar 390233294Sstas memcpy(q, iov[1].data.data, iov[1].data.length); 391233294Sstas q += iov[1].data.length; 392233294Sstas memcpy(q, iov[2].data.data, iov[2].data.length); 393120945Snectar 394233294Sstas free(iov[1].data.data); 395233294Sstas free(iov[2].data.data); 396120945Snectar 397233294Sstas iov[1].data.data = p; 398233294Sstas iov[1].data.length += iov[2].data.length; 399120945Snectar 400233294Sstas iov[2].flags = KRB5_CRYPTO_TYPE_EMPTY; 401233294Sstas iov[2].data.length = 0; 402120945Snectar 403233294Sstas ret = krb5_decrypt_iov_ivec(context, crypto, usage, 404233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 405233294Sstas free(iov[0].data.data); 406233294Sstas free(iov[3].data.data); 407120945Snectar 408233294Sstas if (ret) 409233294Sstas krb5_err(context, 1, ret, "decrypt iov failed: %d", ret); 410120945Snectar 411233294Sstas if (clear->length != iov[1].data.length) 412233294Sstas errx(1, "length incorrect"); 413178825Sdfr 414233294Sstas p = clear->data; 415233294Sstas if (memcmp(iov[1].data.data, p, iov[1].data.length) != 0) 416233294Sstas errx(1, "iov[1] incorrect"); 417120945Snectar 418233294Sstas free(iov[1].data.data); 419120945Snectar 420233294Sstas return 0; 421233294Sstas} 422120945Snectar 423120945Snectar 424233294Sstasstatic int 425233294Sstaskrb_enc_iov(krb5_context context, 426233294Sstas krb5_crypto crypto, 427233294Sstas unsigned usage, 428233294Sstas krb5_data *cipher, 429233294Sstas krb5_data *clear) 430233294Sstas{ 431233294Sstas krb5_crypto_iov iov[3]; 432233294Sstas int ret; 433233294Sstas char *p; 434233294Sstas size_t len; 435178825Sdfr 436233294Sstas p = cipher->data; 437233294Sstas len = cipher->length; 438178825Sdfr 439233294Sstas iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 440233294Sstas krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 441233294Sstas iov[0].data.data = emalloc(iov[0].data.length); 442233294Sstas memcpy(iov[0].data.data, p, iov[0].data.length); 443233294Sstas p += iov[0].data.length; 444233294Sstas len -= iov[0].data.length; 445233294Sstas 446233294Sstas iov[1].flags = KRB5_CRYPTO_TYPE_TRAILER; 447233294Sstas krb5_crypto_length(context, crypto, iov[1].flags, &iov[1].data.length); 448233294Sstas iov[1].data.data = emalloc(iov[1].data.length); 449233294Sstas memcpy(iov[1].data.data, p + len - iov[1].data.length, iov[1].data.length); 450233294Sstas len -= iov[1].data.length; 451233294Sstas 452233294Sstas iov[2].flags = KRB5_CRYPTO_TYPE_DATA; 453233294Sstas iov[2].data.length = len; 454233294Sstas iov[2].data.data = emalloc(len); 455233294Sstas memcpy(iov[2].data.data, p, len); 456233294Sstas 457233294Sstas ret = krb5_decrypt_iov_ivec(context, crypto, usage, 458233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 459233294Sstas if (ret) 460233294Sstas krb5_err(context, 1, ret, "krb_enc_iov decrypt iov failed: %d", ret); 461233294Sstas 462233294Sstas if (clear->length != iov[2].data.length) 463233294Sstas errx(1, "length incorrect"); 464233294Sstas 465233294Sstas p = clear->data; 466233294Sstas if (memcmp(iov[2].data.data, p, iov[2].data.length) != 0) 467233294Sstas errx(1, "iov[2] incorrect"); 468233294Sstas 469233294Sstas free(iov[0].data.data); 470233294Sstas free(iov[1].data.data); 471233294Sstas free(iov[2].data.data); 472233294Sstas 473233294Sstas 474233294Sstas return 0; 475120945Snectar} 476120945Snectar 477178825Sdfrstatic int 478233294Sstaskrb_checksum_iov(krb5_context context, 479233294Sstas krb5_crypto crypto, 480233294Sstas unsigned usage, 481233294Sstas krb5_data *plain) 482178825Sdfr{ 483233294Sstas krb5_crypto_iov iov[4]; 484233294Sstas int ret; 485233294Sstas char *p; 486233294Sstas size_t len; 487120945Snectar 488233294Sstas p = plain->data; 489233294Sstas len = plain->length; 490178825Sdfr 491233294Sstas iov[0].flags = KRB5_CRYPTO_TYPE_CHECKSUM; 492233294Sstas krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); 493233294Sstas iov[0].data.data = emalloc(iov[0].data.length); 494178825Sdfr 495233294Sstas iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 496233294Sstas iov[1].data.length = len; 497233294Sstas iov[1].data.data = p; 498178825Sdfr 499233294Sstas iov[2].flags = KRB5_CRYPTO_TYPE_TRAILER; 500233294Sstas krb5_crypto_length(context, crypto, iov[0].flags, &iov[2].data.length); 501233294Sstas iov[2].data.data = malloc(iov[2].data.length); 502178825Sdfr 503233294Sstas ret = krb5_create_checksum_iov(context, crypto, usage, 504233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 505233294Sstas if (ret) 506233294Sstas krb5_err(context, 1, ret, "krb5_create_checksum_iov failed"); 507178825Sdfr 508233294Sstas ret = krb5_verify_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); 509233294Sstas if (ret) 510233294Sstas krb5_err(context, 1, ret, "krb5_verify_checksum_iov"); 511233294Sstas 512233294Sstas free(iov[0].data.data); 513233294Sstas free(iov[2].data.data); 514233294Sstas 515178825Sdfr return 0; 516178825Sdfr} 517178825Sdfr 518233294Sstas 519178825Sdfrstatic int 520178825Sdfrkrb_enc_mit(krb5_context context, 521178825Sdfr krb5_enctype enctype, 522178825Sdfr krb5_keyblock *key, 523178825Sdfr unsigned usage, 524233294Sstas krb5_data *cipher, 525178825Sdfr krb5_data *clear) 526178825Sdfr{ 527233294Sstas#ifndef HEIMDAL_SMALLER 528178825Sdfr krb5_error_code ret; 529178825Sdfr krb5_enc_data e; 530178825Sdfr krb5_data decrypt; 531178825Sdfr size_t len; 532178825Sdfr 533178825Sdfr e.kvno = 0; 534178825Sdfr e.enctype = enctype; 535178825Sdfr e.ciphertext = *cipher; 536178825Sdfr 537178825Sdfr ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt); 538178825Sdfr if (ret) 539178825Sdfr return ret; 540178825Sdfr 541178825Sdfr if (decrypt.length != clear->length || 542178825Sdfr memcmp(decrypt.data, clear->data, decrypt.length) != 0) { 543178825Sdfr krb5_warnx(context, "clear text not same"); 544178825Sdfr return EINVAL; 545178825Sdfr } 546178825Sdfr 547178825Sdfr krb5_data_free(&decrypt); 548178825Sdfr 549178825Sdfr ret = krb5_c_encrypt_length(context, enctype, clear->length, &len); 550178825Sdfr if (ret) 551178825Sdfr return ret; 552178825Sdfr 553178825Sdfr if (len != cipher->length) { 554178825Sdfr krb5_warnx(context, "c_encrypt_length wrong %lu != %lu", 555178825Sdfr (unsigned long)len, (unsigned long)cipher->length); 556178825Sdfr return EINVAL; 557178825Sdfr } 558233294Sstas#endif /* HEIMDAL_SMALLER */ 559178825Sdfr return 0; 560178825Sdfr} 561178825Sdfr 562178825Sdfr 563178825Sdfrstruct { 564178825Sdfr krb5_enctype enctype; 565178825Sdfr unsigned usage; 566178825Sdfr size_t keylen; 567178825Sdfr void *key; 568178825Sdfr size_t elen; 569178825Sdfr void* edata; 570178825Sdfr size_t plen; 571178825Sdfr void *pdata; 572178825Sdfr} krbencs[] = { 573233294Sstas { 574178825Sdfr ETYPE_AES256_CTS_HMAC_SHA1_96, 575178825Sdfr 7, 576233294Sstas 32, 577178825Sdfr "\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75" 578178825Sdfr "\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65", 579178825Sdfr 44, 580178825Sdfr "\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91" 581178825Sdfr "\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24" 582178825Sdfr "\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd", 583178825Sdfr 16, 584178825Sdfr "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a" 585178825Sdfr } 586178825Sdfr}; 587178825Sdfr 588178825Sdfr 589178825Sdfrstatic int 590178825Sdfrkrb_enc_test(krb5_context context) 591178825Sdfr{ 592178825Sdfr krb5_error_code ret; 593178825Sdfr krb5_crypto crypto; 594178825Sdfr krb5_keyblock kb; 595178825Sdfr krb5_data cipher, plain; 596233294Sstas int i; 597178825Sdfr 598178825Sdfr for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) { 599178825Sdfr 600178825Sdfr kb.keytype = krbencs[i].enctype; 601178825Sdfr kb.keyvalue.length = krbencs[i].keylen; 602178825Sdfr kb.keyvalue.data = krbencs[i].key; 603178825Sdfr 604178825Sdfr ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto); 605178825Sdfr 606178825Sdfr cipher.length = krbencs[i].elen; 607178825Sdfr cipher.data = krbencs[i].edata; 608178825Sdfr plain.length = krbencs[i].plen; 609178825Sdfr plain.data = krbencs[i].pdata; 610233294Sstas 611178825Sdfr ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); 612233294Sstas 613233294Sstas if (ret) 614233294Sstas errx(1, "krb_enc failed with %d for test %d", ret, i); 615233294Sstas 616233294Sstas ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain); 617233294Sstas if (ret) 618233294Sstas errx(1, "krb_enc_iov failed with %d for test %d", ret, i); 619233294Sstas 620233294Sstas ret = krb_enc_iov2(context, crypto, krbencs[i].usage, 621233294Sstas cipher.length, &plain); 622233294Sstas if (ret) 623233294Sstas errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i); 624233294Sstas 625233294Sstas ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain); 626233294Sstas if (ret) 627233294Sstas errx(1, "krb_checksum_iov failed with %d for test %d", ret, i); 628233294Sstas 629178825Sdfr krb5_crypto_destroy(context, crypto); 630178825Sdfr 631233294Sstas ret = krb_enc_mit(context, krbencs[i].enctype, &kb, 632178825Sdfr krbencs[i].usage, &cipher, &plain); 633233294Sstas if (ret) 634233294Sstas errx(1, "krb_enc_mit failed with %d for test %d", ret, i); 635233294Sstas } 636178825Sdfr 637233294Sstas return 0; 638233294Sstas} 639233294Sstas 640233294Sstasstatic int 641233294Sstasiov_test(krb5_context context) 642233294Sstas{ 643233294Sstas krb5_enctype enctype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; 644233294Sstas krb5_error_code ret; 645233294Sstas krb5_crypto crypto; 646233294Sstas krb5_keyblock key; 647233294Sstas krb5_data signonly, in, in2; 648233294Sstas krb5_crypto_iov iov[6]; 649233294Sstas size_t len, i; 650233294Sstas unsigned char *base, *p; 651233294Sstas 652233294Sstas ret = krb5_generate_random_keyblock(context, enctype, &key); 653233294Sstas if (ret) 654233294Sstas krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); 655233294Sstas 656233294Sstas ret = krb5_crypto_init(context, &key, 0, &crypto); 657233294Sstas if (ret) 658233294Sstas krb5_err(context, 1, ret, "krb5_crypto_init"); 659233294Sstas 660233294Sstas 661233294Sstas ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len); 662233294Sstas if (ret) 663233294Sstas krb5_err(context, 1, ret, "krb5_crypto_length"); 664233294Sstas 665233294Sstas signonly.data = "This should be signed"; 666233294Sstas signonly.length = strlen(signonly.data); 667233294Sstas in.data = "inputdata"; 668233294Sstas in.length = strlen(in.data); 669233294Sstas 670233294Sstas in2.data = "INPUTDATA"; 671233294Sstas in2.length = strlen(in2.data); 672233294Sstas 673233294Sstas 674233294Sstas memset(iov, 0, sizeof(iov)); 675233294Sstas 676233294Sstas iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; 677233294Sstas iov[1].flags = KRB5_CRYPTO_TYPE_DATA; 678233294Sstas iov[1].data = in; 679233294Sstas iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 680233294Sstas iov[2].data = signonly; 681233294Sstas iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY; 682233294Sstas iov[4].flags = KRB5_CRYPTO_TYPE_PADDING; 683233294Sstas iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER; 684233294Sstas 685233294Sstas ret = krb5_crypto_length_iov(context, crypto, iov, 686233294Sstas sizeof(iov)/sizeof(iov[0])); 687233294Sstas if (ret) 688233294Sstas krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 689233294Sstas 690233294Sstas for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 691233294Sstas if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 692233294Sstas continue; 693233294Sstas len += iov[i].data.length; 694178825Sdfr } 695178825Sdfr 696233294Sstas base = emalloc(len); 697233294Sstas 698233294Sstas /* 699233294Sstas * Allocate data for the fields 700233294Sstas */ 701233294Sstas 702233294Sstas for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 703233294Sstas if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 704233294Sstas continue;; 705233294Sstas iov[i].data.data = p; 706233294Sstas p += iov[i].data.length; 707233294Sstas } 708233294Sstas assert(iov[1].data.length == in.length); 709233294Sstas memcpy(iov[1].data.data, in.data, iov[1].data.length); 710233294Sstas 711233294Sstas /* 712233294Sstas * Encrypt 713233294Sstas */ 714233294Sstas 715233294Sstas ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, 716233294Sstas sizeof(iov)/sizeof(iov[0]), NULL); 717233294Sstas if (ret) 718233294Sstas krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 719233294Sstas 720233294Sstas /* 721233294Sstas * Decrypt 722233294Sstas */ 723233294Sstas 724233294Sstas ret = krb5_decrypt_iov_ivec(context, crypto, 7, 725233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 726233294Sstas if (ret) 727233294Sstas krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 728233294Sstas 729233294Sstas /* 730233294Sstas * Verify data 731233294Sstas */ 732233294Sstas 733233294Sstas if (krb5_data_cmp(&iov[1].data, &in) != 0) 734233294Sstas krb5_errx(context, 1, "decrypted data not same"); 735233294Sstas 736233294Sstas /* 737233294Sstas * Free memory 738233294Sstas */ 739233294Sstas 740233294Sstas free(base); 741233294Sstas 742233294Sstas /* Set up for second try */ 743233294Sstas 744233294Sstas iov[3].flags = KRB5_CRYPTO_TYPE_DATA; 745233294Sstas iov[3].data = in; 746233294Sstas 747233294Sstas ret = krb5_crypto_length_iov(context, crypto, 748233294Sstas iov, sizeof(iov)/sizeof(iov[0])); 749233294Sstas if (ret) 750233294Sstas krb5_err(context, 1, ret, "krb5_crypto_length_iov"); 751233294Sstas 752233294Sstas for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 753233294Sstas if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 754233294Sstas continue; 755233294Sstas len += iov[i].data.length; 756233294Sstas } 757233294Sstas 758233294Sstas base = emalloc(len); 759233294Sstas 760233294Sstas /* 761233294Sstas * Allocate data for the fields 762233294Sstas */ 763233294Sstas 764233294Sstas for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { 765233294Sstas if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) 766233294Sstas continue;; 767233294Sstas iov[i].data.data = p; 768233294Sstas p += iov[i].data.length; 769233294Sstas } 770233294Sstas assert(iov[1].data.length == in.length); 771233294Sstas memcpy(iov[1].data.data, in.data, iov[1].data.length); 772233294Sstas 773233294Sstas assert(iov[3].data.length == in2.length); 774233294Sstas memcpy(iov[3].data.data, in2.data, iov[3].data.length); 775233294Sstas 776233294Sstas 777233294Sstas 778233294Sstas /* 779233294Sstas * Encrypt 780233294Sstas */ 781233294Sstas 782233294Sstas ret = krb5_encrypt_iov_ivec(context, crypto, 7, 783233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 784233294Sstas if (ret) 785233294Sstas krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); 786233294Sstas 787233294Sstas /* 788233294Sstas * Decrypt 789233294Sstas */ 790233294Sstas 791233294Sstas ret = krb5_decrypt_iov_ivec(context, crypto, 7, 792233294Sstas iov, sizeof(iov)/sizeof(iov[0]), NULL); 793233294Sstas if (ret) 794233294Sstas krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); 795233294Sstas 796233294Sstas /* 797233294Sstas * Verify data 798233294Sstas */ 799233294Sstas 800233294Sstas if (krb5_data_cmp(&iov[1].data, &in) != 0) 801233294Sstas krb5_errx(context, 1, "decrypted data 2.1 not same"); 802233294Sstas 803233294Sstas if (krb5_data_cmp(&iov[3].data, &in2) != 0) 804233294Sstas krb5_errx(context, 1, "decrypted data 2.2 not same"); 805233294Sstas 806233294Sstas /* 807233294Sstas * Free memory 808233294Sstas */ 809233294Sstas 810233294Sstas free(base); 811233294Sstas 812233294Sstas krb5_crypto_destroy(context, crypto); 813233294Sstas 814233294Sstas krb5_free_keyblock_contents(context, &key); 815233294Sstas 816233294Sstas return 0; 817178825Sdfr} 818178825Sdfr 819178825Sdfr 820233294Sstas 821178825Sdfrstatic int 822178825Sdfrrandom_to_key(krb5_context context) 823178825Sdfr{ 824178825Sdfr krb5_error_code ret; 825178825Sdfr krb5_keyblock key; 826178825Sdfr 827178825Sdfr ret = krb5_random_to_key(context, 828178825Sdfr ETYPE_DES3_CBC_SHA1, 829178825Sdfr "\x21\x39\x04\x58\x6A\xBD\x7F" 830178825Sdfr "\x21\x39\x04\x58\x6A\xBD\x7F" 831178825Sdfr "\x21\x39\x04\x58\x6A\xBD\x7F", 832178825Sdfr 21, 833178825Sdfr &key); 834178825Sdfr if (ret){ 835178825Sdfr krb5_warn(context, ret, "random_to_key"); 836178825Sdfr return 1; 837178825Sdfr } 838178825Sdfr if (key.keyvalue.length != 24) 839178825Sdfr return 1; 840178825Sdfr 841178825Sdfr if (memcmp(key.keyvalue.data, 842178825Sdfr "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 843178825Sdfr "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" 844178825Sdfr "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", 845178825Sdfr 24) != 0) 846178825Sdfr return 1; 847178825Sdfr 848178825Sdfr krb5_free_keyblock_contents(context, &key); 849178825Sdfr 850178825Sdfr return 0; 851178825Sdfr} 852178825Sdfr 853120945Snectarint 854120945Snectarmain(int argc, char **argv) 855120945Snectar{ 856120945Snectar krb5_error_code ret; 857120945Snectar krb5_context context; 858120945Snectar int val = 0; 859233294Sstas 860120945Snectar ret = krb5_init_context (&context); 861120945Snectar if (ret) 862120945Snectar errx (1, "krb5_init_context failed: %d", ret); 863120945Snectar 864120945Snectar val |= string_to_key_test(context); 865120945Snectar 866178825Sdfr val |= krb_enc_test(context); 867178825Sdfr val |= random_to_key(context); 868233294Sstas val |= iov_test(context); 869120945Snectar 870120945Snectar if (verbose && val == 0) 871120945Snectar printf("all ok\n"); 872120945Snectar if (val) 873120945Snectar printf("tests failed\n"); 874120945Snectar 875120945Snectar krb5_free_context(context); 876120945Snectar 877120945Snectar return val; 878120945Snectar} 879