216 lines
5.6 KiB
C
216 lines
5.6 KiB
C
#include <com_err.h>
|
|
#include <krb5.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#define krb5_kdb_decode_int16(cp, i16) \
|
|
*((krb5_int16 *) &(i16)) = (((krb5_int16) ((unsigned char) (cp)[0]))| \
|
|
((krb5_int16) ((unsigned char) (cp)[1]) << 8))
|
|
#define encode_int16(i16, cp) \
|
|
{ \
|
|
(cp)[0] = (unsigned char) ((i16) & 0xff); \
|
|
(cp)[1] = (unsigned char) (((i16) >> 8) & 0xff); \
|
|
}
|
|
|
|
krb5_error_code
|
|
krb5_db_fetch_mkey(krb5_context context,
|
|
krb5_enctype etype,
|
|
char *keyfile,
|
|
krb5_keyblock * key)
|
|
{
|
|
krb5_error_code retval;
|
|
|
|
/* from somewhere else */
|
|
krb5_ui_2 enctype;
|
|
FILE *kf;
|
|
|
|
retval = 0;
|
|
key->magic = KV5M_KEYBLOCK;
|
|
|
|
if (!(kf = fopen(keyfile, "r")))
|
|
return KRB5_KDB_CANTREAD_STORED;
|
|
if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
|
|
retval = KRB5_KDB_CANTREAD_STORED;
|
|
goto errout;
|
|
}
|
|
if (key->enctype == ENCTYPE_UNKNOWN)
|
|
key->enctype = enctype;
|
|
else if (enctype != key->enctype) {
|
|
retval = KRB5_KDB_BADSTORED_MKEY;
|
|
goto errout;
|
|
}
|
|
if (fread((krb5_pointer) &key->length,
|
|
sizeof(key->length), 1, kf) != 1) {
|
|
retval = KRB5_KDB_CANTREAD_STORED;
|
|
goto errout;
|
|
}
|
|
if (!key->length || ((int) key->length) < 0) {
|
|
retval = KRB5_KDB_BADSTORED_MKEY;
|
|
goto errout;
|
|
}
|
|
|
|
if (!(key->contents = (krb5_octet *)malloc(key->length))) {
|
|
retval = ENOMEM;
|
|
goto errout;
|
|
}
|
|
if (fread((krb5_pointer) key->contents,
|
|
sizeof(key->contents[0]), key->length, kf)
|
|
!= key->length) {
|
|
retval = KRB5_KDB_CANTREAD_STORED;
|
|
memset(key->contents, 0, key->length);
|
|
free(key->contents);
|
|
key->contents = 0;
|
|
} else
|
|
retval = 0;
|
|
|
|
errout:
|
|
(void) fclose(kf);
|
|
return retval;
|
|
}
|
|
|
|
|
|
static int
|
|
read_octet_string(char *str, krb5_octet *buf, size_t len)
|
|
{
|
|
int c;
|
|
int i, retval;
|
|
char *s;
|
|
|
|
s = str;
|
|
|
|
retval = 0;
|
|
for (i=0; i<len; i++) {
|
|
if (sscanf(s, "%02x", &c) != 1) {
|
|
retval = 1;
|
|
free(s);
|
|
break;
|
|
}
|
|
buf[i] = (krb5_octet) c;
|
|
if(i+1 < len) {
|
|
s++;
|
|
s++;
|
|
}
|
|
}
|
|
s = NULL;
|
|
return(retval);
|
|
}
|
|
|
|
void usage()
|
|
{
|
|
fprintf(stderr, "Usage: "
|
|
"EncryptWithMasterKey -sf stashfilename -d data [-e enctype]\n"
|
|
"\t [-sf stashfilename] \n"
|
|
"\t [-d the data to encrypt]\n"
|
|
"\t [-e encryption type of the master key] (default des3-cbc-sha1)\n\n"
|
|
"\t valid enctypes are:\n\n"
|
|
"\t des-cbc-crc, des-cbc-md4, des-cbc-md5, des, des-cbc-raw,\n"
|
|
"\t des3-cbc-raw, des3-cbc-sha1, des3-hmac-sha1, des3-cbc-sha1-kd,\n"
|
|
"\t des-hmac-sha1, arcfour-hmac, rc4-hmac, arcfour-hmac-md5,\n"
|
|
"\t arcfour-hmac-exp, rc4-hmac-exp, arcfour-hmac-md5-exp,\n"
|
|
"\t aes128-cts-hmac-sha1-96, aes128-cts, aes256-cts-hmac-sha1-96,\n"
|
|
"\t aes256-cts\n");
|
|
exit(1);
|
|
}
|
|
|
|
#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
krb5_context context;
|
|
krb5_error_code retval;
|
|
krb5_keyblock master_keyblock;
|
|
krb5_data plain;
|
|
krb5_enc_data cipher;
|
|
size_t plainlen = 0;
|
|
size_t enclen = 0;
|
|
char *koptarg;
|
|
char *stashfile = NULL;
|
|
char *data = NULL;
|
|
int i = 0;
|
|
|
|
master_keyblock.enctype = ENCTYPE_DES3_CBC_SHA1;
|
|
|
|
argv++; argc--;
|
|
while (*argv) {
|
|
if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
|
|
stashfile = koptarg;
|
|
} else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
|
|
data = koptarg;
|
|
} else if (strcmp(*argv, "-e") == 0 && ARG_VAL) {
|
|
if (krb5_string_to_enctype(koptarg, &master_keyblock.enctype))
|
|
{
|
|
com_err(argv[0], 0, "%s is an invalid enctype", koptarg);
|
|
usage();
|
|
}
|
|
} else {
|
|
usage();
|
|
}
|
|
argv++; argc--;
|
|
}
|
|
|
|
if (data == NULL || stashfile == NULL)
|
|
usage();
|
|
|
|
|
|
retval = krb5_init_context(&context);
|
|
if( retval )
|
|
{
|
|
com_err(argv[0], retval, "while initializing krb5_context");
|
|
exit(1);
|
|
}
|
|
|
|
retval = krb5_db_fetch_mkey(context,
|
|
master_keyblock.enctype,
|
|
stashfile,
|
|
&master_keyblock);
|
|
if( retval )
|
|
{
|
|
com_err(argv[0], retval, "while fetching master key");
|
|
exit(1);
|
|
}
|
|
|
|
plainlen = strlen(data)/2;
|
|
|
|
plain.data = (char *) malloc(plainlen);
|
|
plain.length = plainlen;
|
|
|
|
read_octet_string(data, (krb5_octet*)plain.data, plainlen);
|
|
|
|
retval = krb5_c_encrypt_length(context,
|
|
master_keyblock.enctype,
|
|
plain.length, &enclen);
|
|
if( retval )
|
|
{
|
|
com_err(argv[0], retval, "while calculating cipher data length");
|
|
exit(1);
|
|
}
|
|
|
|
cipher.ciphertext.data = (char *) malloc(enclen);
|
|
cipher.ciphertext.length = enclen;
|
|
|
|
retval = krb5_c_encrypt(context, &master_keyblock, /* XXX */ 0, 0,
|
|
&plain, &cipher);
|
|
if( retval )
|
|
{
|
|
com_err(argv[0], retval, "while encrypting data");
|
|
exit(1);
|
|
}
|
|
|
|
/* first print out the length of the decrypted hash */
|
|
|
|
char l[2];
|
|
encode_int16((unsigned int)plainlen, l);
|
|
printf("%02x%02x", l[0], l[1]);
|
|
|
|
/* now print the encrypted key */
|
|
for(i = 0; i < cipher.ciphertext.length; ++i)
|
|
{
|
|
printf("%02x",(unsigned char)cipher.ciphertext.data[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
return 0;
|
|
}
|
|
|