* dk.h: Add prototypes for krb5_marc_dk_*
authorTom Yu <tlyu@mit.edu>
Tue, 5 Jan 1999 05:14:31 +0000 (05:14 +0000)
committerTom Yu <tlyu@mit.edu>
Tue, 5 Jan 1999 05:14:31 +0000 (05:14 +0000)
* dk_encrypt.c (krb5_marc_dk_encrypt): Add compat for 32-bit
length coded ciphertext.

* dk_decrypt.c (krb5_marc_dk_decrypt): Add compat for 32-bit
length coded ciphertext.

* checksum.c: Add compat for 32-bit length included checksum.
Note that nothing uses this at the moment, and probably
shouldn't.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11098 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/dk/ChangeLog
src/lib/crypto/dk/checksum.c
src/lib/crypto/dk/dk.h
src/lib/crypto/dk/dk_decrypt.c
src/lib/crypto/dk/dk_encrypt.c

index a8a4bda506de4b68de25c62b936f82a92b8c7c94..7f3300a9457a10fce2a1082cbf5185afe0948f11 100644 (file)
@@ -1,3 +1,17 @@
+Tue Jan  5 00:09:13 1999  Tom Yu  <tlyu@mit.edu>
+
+       * dk.h: Add prototypes for krb5_marc_dk_*.
+
+       * dk_encrypt.c (krb5_marc_dk_encrypt): Add compat for 32-bit
+       length coded ciphertext.
+
+       * dk_decrypt.c (krb5_marc_dk_decrypt): Add compat for 32-bit
+       length coded ciphertext.
+
+       * checksum.c: Add compat for 32-bit length included checksum.
+       Note that nothing uses this at the moment, and probably
+       shouldn't.
+
 1998-11-13  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Set the myfulldir and mydir variables (which are
index db64e6cb65a6f88a6023bf8c6690b10b288aa970..b9318d23952644838c26c06cb1287300a25b4051 100644 (file)
@@ -102,3 +102,84 @@ cleanup:
 
     return(ret);
 }
+
+#ifdef ATHENA_DES3_KLUDGE
+krb5_error_code
+krb5_marc_dk_make_checksum(hash, key, usage, input, output)
+     krb5_const struct krb5_hash_provider *hash;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *input;
+     krb5_data *output;
+{
+    int i;
+    struct krb5_enc_provider *enc;
+    size_t blocksize, keybytes, keylength;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data datain[2];
+    unsigned char *kcdata;
+    krb5_keyblock kc;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+       if (krb5_enctypes_list[i].etype == key->enctype)
+           break;
+    }
+
+    if (i == krb5_enctypes_length)
+       return(KRB5_BAD_ENCTYPE);
+
+    enc = krb5_enctypes_list[i].enc;
+
+    /* allocate and set to-be-derived keys */
+
+    (*(enc->block_size))(&blocksize);
+    (*(enc->keysize))(&keybytes, &keylength);
+
+    /* key->length will be tested in enc->encrypt
+       output->length will be tested in krb5_hmac */
+
+    if ((kcdata = (unsigned char *) malloc(keylength)) == NULL)
+       return(ENOMEM);
+
+    kc.contents = kcdata;
+    kc.length = keylength;
+
+    /* derive the key */
+    datain[0].data = constantdata;
+    datain[0].length = K5CLENGTH;
+
+    datain[0].data[0] = (usage>>24)&0xff;
+    datain[0].data[1] = (usage>>16)&0xff;
+    datain[0].data[2] = (usage>>8)&0xff;
+    datain[0].data[3] = usage&0xff;
+
+    datain[0].data[4] = 0x99;
+
+    if (ret = krb5_derive_key(enc, key, &kc, &datain[0]))
+       goto cleanup;
+
+    /* hash the data */
+
+    datain[0].length = 4;
+    datain[0].data[0] = (input->length>>24)&0xff;
+    datain[0].data[1] = (input->length>>16)&0xff;
+    datain[0].data[2] = (input->length>>8)&0xff;
+    datain[0].data[3] = input->length&0xff;
+
+    datain[1] = *input;
+
+    if (ret = krb5_hmac(hash, &kc, 2, datain, output))
+       memset(output->data, 0, output->length);
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(kcdata, 0, keylength);
+
+    free(kcdata);
+
+    return(ret);
+}
+#endif /* ATHENA_DES3_KLUDGE */
index e4acddabc01a6017e3338325ce0b093a48d90506..996fed1f2157768e07d90dbd6a51aa23086add96 100644 (file)
@@ -59,3 +59,29 @@ krb5_error_code krb5_dk_make_checksum
 KRB5_PROTOTYPE((krb5_const struct krb5_hash_provider *hash,
                krb5_const krb5_keyblock *key, krb5_keyusage usage,
                krb5_const krb5_data *input, krb5_data *output));
+
+#ifdef ATHENA_DES3_KLUDGE
+void krb5_marc_dk_encrypt_length
+KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc,
+               krb5_const struct krb5_hash_provider *hash,
+               size_t input, size_t *length));
+
+krb5_error_code krb5_marc_dk_encrypt
+KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc,
+               krb5_const struct krb5_hash_provider *hash,
+               krb5_const krb5_keyblock *key, krb5_keyusage usage,
+               krb5_const krb5_data *ivec,
+               krb5_const krb5_data *input, krb5_data *output));
+
+krb5_error_code krb5_marc_dk_decrypt
+KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc,
+               krb5_const struct krb5_hash_provider *hash,
+               krb5_const krb5_keyblock *key, krb5_keyusage usage,
+               krb5_const krb5_data *ivec, krb5_const krb5_data *input,
+               krb5_data *arg_output));
+
+krb5_error_code krb5_marc_dk_make_checksum
+KRB5_PROTOTYPE((krb5_const struct krb5_hash_provider *hash,
+               krb5_const krb5_keyblock *key, krb5_keyusage usage,
+               krb5_const krb5_data *input, krb5_data *output));
+#endif /* ATHENA_DES3_KLUDGE */
index 9fedffbc09fab3c48136c7f5886a353ed3673a23..71fdb80d0f8a76f97a808388c5a8934a593b3d40 100644 (file)
@@ -149,3 +149,134 @@ cleanup:
 
     return(ret);
 }
+
+#ifdef ATHENA_DES3_KLUDGE
+krb5_error_code
+krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output)
+     krb5_const struct krb5_enc_provider *enc;
+     krb5_const struct krb5_hash_provider *hash;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *ivec;
+     krb5_const krb5_data *input;
+     krb5_data *output;
+{
+    krb5_error_code ret;
+    size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen;
+    unsigned char *plaindata, *kedata, *kidata, *cksum;
+    krb5_keyblock ke, ki;
+    krb5_data d1, d2;
+    unsigned char constantdata[K5CLENGTH];
+
+    /* allocate and set up ciphertext and to-be-derived keys */
+
+    (*(hash->hash_size))(&hashsize);
+    (*(enc->block_size))(&blocksize);
+    (*(enc->keysize))(&keybytes, &keylength);
+
+    enclen = input->length - hashsize;
+
+    if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
+       return(ENOMEM);
+    if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
+       free(kedata);
+       return(ENOMEM);
+    }
+    if ((plaindata = (unsigned char *) malloc(enclen)) == NULL) {
+       free(kidata);
+       free(kedata);
+       return(ENOMEM);
+    }
+    if ((cksum = (unsigned char *) malloc(hashsize)) == NULL) {
+       free(plaindata);
+       free(kidata);
+       free(kedata);
+       return(ENOMEM);
+    }
+
+    ke.contents = kedata;
+    ke.length = keylength;
+    ki.contents = kidata;
+    ki.length = keylength;
+
+    /* derive the keys */
+
+    d1.data = constantdata;
+    d1.length = K5CLENGTH;
+
+    d1.data[0] = (usage>>24)&0xff;
+    d1.data[1] = (usage>>16)&0xff;
+    d1.data[2] = (usage>>8)&0xff;
+    d1.data[3] = usage&0xff;
+
+    d1.data[4] = 0xAA;
+
+    if (ret = krb5_derive_key(enc, key, &ke, &d1))
+       goto cleanup;
+
+    d1.data[4] = 0x55;
+
+    if (ret = krb5_derive_key(enc, key, &ki, &d1))
+       goto cleanup;
+
+    /* decrypt the ciphertext */
+
+    d1.length = enclen;
+    d1.data = input->data;
+
+    d2.length = enclen;
+    d2.data = plaindata;
+
+    if (ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2)))
+       goto cleanup;
+
+    /* verify the hash */
+
+    d1.length = hashsize;
+    d1.data = cksum;
+
+    if (ret = krb5_hmac(hash, &ki, 1, &d2, &d1))
+       goto cleanup;
+
+    if (memcmp(cksum, input->data+enclen, hashsize) != 0) {
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       goto cleanup;
+    }
+
+    /* because this encoding isn't self-describing wrt length, the
+       best we can do here is to compute the length minus the
+       confounder. */
+
+    /* get the real plaintext length and copy the data into the output */
+
+    plainlen = ((((plaindata+blocksize)[0])<<24) |
+               (((plaindata+blocksize)[1])<<16) |
+               (((plaindata+blocksize)[2])<<8) |
+               ((plaindata+blocksize)[3]));
+
+    if (plainlen > (enclen - blocksize - 4))
+       return(KRB5_BAD_MSIZE);
+
+    if (output->length < plainlen)
+       return(KRB5_BAD_MSIZE);
+
+    output->length = plainlen;
+
+    memcpy(output->data, d2.data+4+blocksize, output->length);
+
+    ret = 0;
+
+cleanup:
+    memset(kedata, 0, keylength);
+    memset(kidata, 0, keylength);
+    memset(plaindata, 0, enclen);
+    memset(cksum, 0, hashsize);
+
+    free(cksum);
+    free(plaindata);
+    free(kidata);
+    free(kedata);
+
+    return(ret);
+}
+#endif /* ATHENA_DES3_KLUDGE */
index 4a3a00b30018a4c6f16875bd5e57203ec7259fb7..a1b85a3acabf01a18790ca6a4b98978b9582388e 100644 (file)
@@ -165,3 +165,140 @@ cleanup:
 
     return(ret);
 }
+
+#ifdef ATHENA_DES3_KLUDGE
+void
+krb5_marc_dk_encrypt_length(enc, hash, inputlen, length)
+     krb5_const struct krb5_enc_provider *enc;
+     krb5_const struct krb5_hash_provider *hash;
+     size_t inputlen;
+     size_t *length;
+{
+    size_t blocksize, hashsize;
+
+    (*(enc->block_size))(&blocksize);
+    (*(hash->hash_size))(&hashsize);
+
+    *length = krb5_roundup(blocksize+4+inputlen, blocksize) + hashsize;
+}
+
+krb5_error_code
+krb5_marc_dk_encrypt(enc, hash, key, usage, ivec, input, output)
+     krb5_const struct krb5_enc_provider *enc;
+     krb5_const struct krb5_hash_provider *hash;
+     krb5_const krb5_keyblock *key;
+     krb5_keyusage usage;
+     krb5_const krb5_data *ivec;
+     krb5_const krb5_data *input;
+     krb5_data *output;
+{
+    size_t blocksize, keybytes, keylength, plainlen, enclen;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data d1, d2;
+    unsigned char *plaintext, *kedata, *kidata;
+    krb5_keyblock ke, ki;
+
+    /* allocate and set up plaintext and to-be-derived keys */
+
+    (*(enc->block_size))(&blocksize);
+    (*(enc->keysize))(&keybytes, &keylength);
+    plainlen = krb5_roundup(blocksize+4+input->length, blocksize);
+
+    krb5_dk_encrypt_length(enc, hash, input->length, &enclen);
+
+    /* key->length, ivec will be tested in enc->encrypt */
+
+    if (output->length < enclen)
+       return(KRB5_BAD_MSIZE);
+
+    if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
+       return(ENOMEM);
+    if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
+       free(kedata);
+       return(ENOMEM);
+    }
+    if ((plaintext = (unsigned char *) malloc(plainlen)) == NULL) {
+       free(kidata);
+       free(kedata);
+       return(ENOMEM);
+    }
+
+    ke.contents = kedata;
+    ke.length = keylength;
+    ki.contents = kidata;
+    ki.length = keylength;
+
+    /* derive the keys */
+
+    d1.data = constantdata;
+    d1.length = K5CLENGTH;
+
+    d1.data[0] = (usage>>24)&0xff;
+    d1.data[1] = (usage>>16)&0xff;
+    d1.data[2] = (usage>>8)&0xff;
+    d1.data[3] = usage&0xff;
+
+    d1.data[4] = 0xAA;
+
+    if (ret = krb5_derive_key(enc, key, &ke, &d1))
+       goto cleanup;
+
+    d1.data[4] = 0x55;
+
+    if (ret = krb5_derive_key(enc, key, &ki, &d1))
+       goto cleanup;
+
+    /* put together the plaintext */
+
+    d1.length = blocksize;
+    d1.data = plaintext;
+
+    if (ret = krb5_c_random_make_octets(/* XXX */ 0, &d1))
+       goto cleanup;
+
+    (plaintext+blocksize)[0] = (input->length>>24)&0xff;
+    (plaintext+blocksize)[1] = (input->length>>16)&0xff;
+    (plaintext+blocksize)[2] = (input->length>>8)&0xff;
+    (plaintext+blocksize)[3] = input->length&0xff;
+
+    memcpy(plaintext+blocksize+4, input->data, input->length);
+
+    memset(plaintext+blocksize+4+input->length, 0,
+          plainlen - (blocksize+4+input->length));
+
+    /* encrypt the plaintext */
+
+    d1.length = plainlen;
+    d1.data = plaintext;
+
+    d2.length = plainlen;
+    d2.data = output->data;
+
+    if (ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2)))
+       goto cleanup;
+
+    /* hash the plaintext */
+
+    d2.length = enclen - plainlen;
+    d2.data = output->data+plainlen;
+
+    output->length = enclen;
+
+    if (ret = krb5_hmac(hash, &ki, 1, &d1, &d2))
+       memset(d2.data, 0, d2.length);
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(kedata, 0, keylength);
+    memset(kidata, 0, keylength);
+    memset(plaintext, 0, plainlen);
+
+    free(plaintext);
+    free(kidata);
+    free(kedata);
+
+    return(ret);
+}
+#endif /* ATHENA_DES3_KLUDGE */