Blame src/lib/crypto/crypto_tests/t_encrypt.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* lib/crypto/crypto_tests/t_encrypt.c */
Packit fd8b60
/*
Packit fd8b60
 * Copyright 2001, 2008 by the Massachusetts Institute of Technology.
Packit fd8b60
 * All Rights Reserved.
Packit fd8b60
 *
Packit fd8b60
 * Export of this software from the United States of America may
Packit fd8b60
 *   require a specific license from the United States Government.
Packit fd8b60
 *   It is the responsibility of any person or organization contemplating
Packit fd8b60
 *   export to obtain such a license before exporting.
Packit fd8b60
 *
Packit fd8b60
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
Packit fd8b60
 * distribute this software and its documentation for any purpose and
Packit fd8b60
 * without fee is hereby granted, provided that the above copyright
Packit fd8b60
 * notice appear in all copies and that both that copyright notice and
Packit fd8b60
 * this permission notice appear in supporting documentation, and that
Packit fd8b60
 * the name of M.I.T. not be used in advertising or publicity pertaining
Packit fd8b60
 * to distribution of the software without specific, written prior
Packit fd8b60
 * permission.  Furthermore if you modify this software you must label
Packit fd8b60
 * your software as modified software and not distribute it in such a
Packit fd8b60
 * fashion that it might be confused with the original M.I.T. software.
Packit fd8b60
 * M.I.T. makes no representations about the suitability of
Packit fd8b60
 * this software for any purpose.  It is provided "as is" without express
Packit fd8b60
 * or implied warranty.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 *
Packit fd8b60
 * <<< Description >>>
Packit fd8b60
 */
Packit fd8b60
/*
Packit fd8b60
 * Some black-box tests of crypto systems.  Make sure that we can decrypt things we encrypt, etc.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include "crypto_int.h"
Packit fd8b60
#include <stdio.h>
Packit fd8b60
Packit fd8b60
/* What enctypes should we test?*/
Packit fd8b60
krb5_enctype interesting_enctypes[] = {
Packit fd8b60
    ENCTYPE_ARCFOUR_HMAC,
Packit fd8b60
    ENCTYPE_ARCFOUR_HMAC_EXP,
Packit fd8b60
    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
Packit fd8b60
    ENCTYPE_AES128_CTS_HMAC_SHA1_96,
Packit fd8b60
    ENCTYPE_CAMELLIA128_CTS_CMAC,
Packit fd8b60
    ENCTYPE_CAMELLIA256_CTS_CMAC,
Packit fd8b60
    ENCTYPE_AES128_CTS_HMAC_SHA256_128,
Packit fd8b60
    ENCTYPE_AES256_CTS_HMAC_SHA384_192,
Packit fd8b60
    0
Packit fd8b60
};
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test(const char *msg, krb5_error_code retval)
Packit fd8b60
{
Packit fd8b60
    printf("%s: . . . ", msg);
Packit fd8b60
    if (retval) {
Packit fd8b60
        printf("Failed: %s\n", error_message(retval));
Packit fd8b60
        abort();
Packit fd8b60
    } else
Packit fd8b60
        printf("OK\n");
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static int compare_results(krb5_data *d1, krb5_data *d2)
Packit fd8b60
{
Packit fd8b60
    if (d1->length != d2->length) {
Packit fd8b60
        /* Decryption can leave a little trailing cruft.
Packit fd8b60
           For the current cryptosystems, this can be up to 7 bytes.  */
Packit fd8b60
        if (d1->length + 8 <= d2->length)
Packit fd8b60
            return EINVAL;
Packit fd8b60
        if (d1->length > d2->length)
Packit fd8b60
            return EINVAL;
Packit fd8b60
    }
Packit fd8b60
    if (memcmp(d1->data, d2->data, d1->length)) {
Packit fd8b60
        return EINVAL;
Packit fd8b60
    }
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
display(const char *msg, const krb5_data *d)
Packit fd8b60
{
Packit fd8b60
    unsigned int i;
Packit fd8b60
Packit fd8b60
    printf("%s:", msg);
Packit fd8b60
    for (i = 0; i < d->length; i++)
Packit fd8b60
        printf(" %02X", (unsigned char) d->data[i]);
Packit fd8b60
    printf("\n");
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
int
Packit fd8b60
main ()
Packit fd8b60
{
Packit fd8b60
    krb5_context context = 0;
Packit fd8b60
    krb5_data  in, in2, out, out2, check, check2, state, signdata;
Packit fd8b60
    krb5_crypto_iov iov[5];
Packit fd8b60
    int i, j, pos;
Packit fd8b60
    unsigned int dummy;
Packit fd8b60
    size_t len;
Packit fd8b60
    krb5_enc_data enc_out, enc_out2;
Packit fd8b60
    krb5_keyblock *keyblock;
Packit fd8b60
    krb5_key key;
Packit fd8b60
Packit fd8b60
    memset(iov, 0, sizeof(iov));
Packit fd8b60
Packit fd8b60
    in.data = "This is a test.\n";
Packit fd8b60
    in.length = strlen (in.data);
Packit fd8b60
    in2.data = "This is another test.\n";
Packit fd8b60
    in2.length = strlen (in2.data);
Packit fd8b60
Packit fd8b60
    test ("Seeding random number generator",
Packit fd8b60
          krb5_c_random_seed (context, &in);;
Packit fd8b60
Packit fd8b60
    /* Set up output buffers. */
Packit fd8b60
    out.data = malloc(2048);
Packit fd8b60
    out2.data = malloc(2048);
Packit fd8b60
    check.data = malloc(2048);
Packit fd8b60
    check2.data = malloc(2048);
Packit fd8b60
    if (out.data == NULL || out2.data == NULL
Packit fd8b60
        || check.data == NULL || check2.data == NULL)
Packit fd8b60
        abort();
Packit fd8b60
    out.magic = KV5M_DATA;
Packit fd8b60
    out.length = 2048;
Packit fd8b60
    out2.magic = KV5M_DATA;
Packit fd8b60
    out2.length = 2048;
Packit fd8b60
    check.length = 2048;
Packit fd8b60
    check2.length = 2048;
Packit fd8b60
Packit fd8b60
    for (i = 0; interesting_enctypes[i]; i++) {
Packit fd8b60
        krb5_enctype enctype = interesting_enctypes [i];
Packit fd8b60
Packit fd8b60
        printf ("Testing enctype %d\n", enctype);
Packit fd8b60
        test ("Initializing a keyblock",
Packit fd8b60
              krb5_init_keyblock (context, enctype, 0, &keyblock));
Packit fd8b60
        test ("Generating random keyblock",
Packit fd8b60
              krb5_c_make_random_key (context, enctype, keyblock));
Packit fd8b60
        test ("Creating opaque key from keyblock",
Packit fd8b60
              krb5_k_create_key (context, keyblock, &key));
Packit fd8b60
Packit fd8b60
        enc_out.ciphertext = out;
Packit fd8b60
        enc_out2.ciphertext = out2;
Packit fd8b60
        /* We use an intermediate `len' because size_t may be different size
Packit fd8b60
           than `int' */
Packit fd8b60
        krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len;;
Packit fd8b60
        enc_out.ciphertext.length = len;
Packit fd8b60
Packit fd8b60
        /* Encrypt, decrypt, and see if we got the plaintext back again. */
Packit fd8b60
        test ("Encrypting (c)",
Packit fd8b60
              krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out));
Packit fd8b60
        display ("Enc output", &enc_out.ciphertext);
Packit fd8b60
        test ("Decrypting",
Packit fd8b60
              krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check);;
Packit fd8b60
        test ("Comparing", compare_results (&in, &check);;
Packit fd8b60
Packit fd8b60
        /* Try again with the opaque-key-using variants. */
Packit fd8b60
        memset(out.data, 0, out.length);
Packit fd8b60
        test ("Encrypting (k)",
Packit fd8b60
              krb5_k_encrypt (context, key, 7, 0, &in, &enc_out));
Packit fd8b60
        display ("Enc output", &enc_out.ciphertext);
Packit fd8b60
        test ("Decrypting",
Packit fd8b60
              krb5_k_decrypt (context, key, 7, 0, &enc_out, &check);;
Packit fd8b60
        test ("Comparing", compare_results (&in, &check);;
Packit fd8b60
Packit fd8b60
        /* Check if this enctype supports IOV encryption. */
Packit fd8b60
        if ( krb5_c_crypto_length(context, keyblock->enctype,
Packit fd8b60
                                  KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){
Packit fd8b60
            /* Set up iovecs for stream decryption. */
Packit fd8b60
            memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
Packit fd8b60
            iov[0].flags= KRB5_CRYPTO_TYPE_STREAM;
Packit fd8b60
            iov[0].data.data = out2.data;
Packit fd8b60
            iov[0].data.length = enc_out.ciphertext.length;
Packit fd8b60
            iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
Packit fd8b60
Packit fd8b60
            /* Decrypt the encrypted data from above and check it. */
Packit fd8b60
            test("IOV stream decrypting (c)",
Packit fd8b60
                 krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2));
Packit fd8b60
            test("Comparing results",
Packit fd8b60
                 compare_results(&in, &iov[1].data));
Packit fd8b60
Packit fd8b60
            /* Try again with the opaque-key-using variant. */
Packit fd8b60
            memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
Packit fd8b60
            test("IOV stream decrypting (k)",
Packit fd8b60
                 krb5_k_decrypt_iov( context, key, 7, 0, iov, 2));
Packit fd8b60
            test("Comparing results",
Packit fd8b60
                 compare_results(&in, &iov[1].data));
Packit fd8b60
Packit fd8b60
            /* Set up iovecs for AEAD encryption. */
Packit fd8b60
            signdata.magic = KV5M_DATA;
Packit fd8b60
            signdata.data = (char *) "This should be signed";
Packit fd8b60
            signdata.length = strlen(signdata.data);
Packit fd8b60
            iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
Packit fd8b60
            iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
Packit fd8b60
            iov[1].data = in; /*We'll need to copy memory before encrypt*/
Packit fd8b60
            iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
Packit fd8b60
            iov[2].data = signdata;
Packit fd8b60
            iov[3].flags = KRB5_CRYPTO_TYPE_PADDING;
Packit fd8b60
            iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER;
Packit fd8b60
Packit fd8b60
            /* "Allocate" data for the iovec buffers from the "out" buffer. */
Packit fd8b60
            test("Setting up iov lengths",
Packit fd8b60
                 krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5));
Packit fd8b60
            for (j=0,pos=0; j <= 4; j++ ){
Packit fd8b60
                if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
Packit fd8b60
                    continue;
Packit fd8b60
                iov[j].data.data = &out.data[pos];
Packit fd8b60
                pos += iov[j].data.length;
Packit fd8b60
            }
Packit fd8b60
            assert (iov[1].data.length == in.length);
Packit fd8b60
            memcpy(iov[1].data.data, in.data, in.length);
Packit fd8b60
Packit fd8b60
            /* Encrypt and decrypt in place, and check the result. */
Packit fd8b60
            test("iov encrypting (c)",
Packit fd8b60
                 krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5));
Packit fd8b60
            assert(iov[1].data.length == in.length);
Packit fd8b60
            display("Header", &iov[0].data);
Packit fd8b60
            display("Data", &iov[1].data);
Packit fd8b60
            display("Padding", &iov[3].data);
Packit fd8b60
            display("Trailer", &iov[4].data);
Packit fd8b60
            test("iov decrypting",
Packit fd8b60
                 krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5));
Packit fd8b60
            test("Comparing results",
Packit fd8b60
                 compare_results(&in, &iov[1].data));
Packit fd8b60
Packit fd8b60
            /* Try again with opaque-key-using variants. */
Packit fd8b60
            test("iov encrypting (k)",
Packit fd8b60
                 krb5_k_encrypt_iov(context, key, 7, 0, iov, 5));
Packit fd8b60
            assert(iov[1].data.length == in.length);
Packit fd8b60
            display("Header", &iov[0].data);
Packit fd8b60
            display("Data", &iov[1].data);
Packit fd8b60
            display("Padding", &iov[3].data);
Packit fd8b60
            display("Trailer", &iov[4].data);
Packit fd8b60
            test("iov decrypting",
Packit fd8b60
                 krb5_k_decrypt_iov(context, key, 7, 0, iov, 5));
Packit fd8b60
            test("Comparing results",
Packit fd8b60
                 compare_results(&in, &iov[1].data));
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        enc_out.ciphertext.length = out.length;
Packit fd8b60
        check.length = 2048;
Packit fd8b60
Packit fd8b60
        test ("init_state",
Packit fd8b60
              krb5_c_init_state (context, keyblock, 7, &state));
Packit fd8b60
        test ("Encrypting with state",
Packit fd8b60
              krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out));
Packit fd8b60
        display ("Enc output", &enc_out.ciphertext);
Packit fd8b60
        test ("Encrypting again with state",
Packit fd8b60
              krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2));
Packit fd8b60
        display ("Enc output", &enc_out2.ciphertext);
Packit fd8b60
        test ("free_state",
Packit fd8b60
              krb5_c_free_state (context, keyblock, &state));
Packit fd8b60
        test ("init_state",
Packit fd8b60
              krb5_c_init_state (context, keyblock, 7, &state));
Packit fd8b60
        test ("Decrypting with state",
Packit fd8b60
              krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check);;
Packit fd8b60
        test ("Decrypting again with state",
Packit fd8b60
              krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2));
Packit fd8b60
        test ("free_state",
Packit fd8b60
              krb5_c_free_state (context, keyblock, &state));
Packit fd8b60
        test ("Comparing",
Packit fd8b60
              compare_results (&in, &check);;
Packit fd8b60
        test ("Comparing",
Packit fd8b60
              compare_results (&in2, &check2));
Packit fd8b60
Packit fd8b60
        krb5_free_keyblock (context, keyblock);
Packit fd8b60
        krb5_k_free_key (context, key);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* Test the RC4 decrypt fallback from key usage 9 to 8. */
Packit fd8b60
    test ("Initializing an RC4 keyblock",
Packit fd8b60
          krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock));
Packit fd8b60
    test ("Generating random RC4 key",
Packit fd8b60
          krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock));
Packit fd8b60
    enc_out.ciphertext = out;
Packit fd8b60
    krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len;;
Packit fd8b60
    enc_out.ciphertext.length = len;
Packit fd8b60
    check.length = 2048;
Packit fd8b60
    test ("Encrypting with RC4 key usage 8",
Packit fd8b60
          krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out));
Packit fd8b60
    display ("Enc output", &enc_out.ciphertext);
Packit fd8b60
    test ("Decrypting with RC4 key usage 9",
Packit fd8b60
          krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check);;
Packit fd8b60
    test ("Comparing", compare_results (&in, &check);;
Packit fd8b60
Packit fd8b60
    krb5_free_keyblock (context, keyblock);
Packit fd8b60
    free(out.data);
Packit fd8b60
    free(out2.data);
Packit fd8b60
    free(check.data);
Packit fd8b60
    free(check2.data);
Packit fd8b60
    return 0;
Packit fd8b60
}