File EncryptWithMasterKey.c of Package krb5

#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;
}

openSUSE Build Service is sponsored by