|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/* lib/crypto/openssl/enc_provider/rc4.c */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright (C) 2009 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 |
* Copyright (c) 2000 by Computer Science Laboratory,
|
|
Packit |
fd8b60 |
* Rensselaer Polytechnic Institute
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* #include STD_DISCLAIMER
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "crypto_int.h"
|
|
Packit |
fd8b60 |
#include <openssl/evp.h>
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* The loopback field is a pointer to the structure. If the application copies
|
|
Packit |
fd8b60 |
* the state (not a valid operation, but one which happens to works with some
|
|
Packit |
fd8b60 |
* other enc providers), we can detect it via the loopback field and return a
|
|
Packit |
fd8b60 |
* sane error code.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
struct arcfour_state {
|
|
Packit |
fd8b60 |
struct arcfour_state *loopback;
|
|
Packit |
fd8b60 |
EVP_CIPHER_CTX *ctx;
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define RC4_KEY_SIZE 16
|
|
Packit |
fd8b60 |
#define RC4_BLOCK_SIZE 1
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Interface layer to krb5 crypto layer */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* The workhorse of the arcfour system,
|
|
Packit |
fd8b60 |
* this impliments the cipher
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* In-place IOV crypto */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
|
|
Packit |
fd8b60 |
size_t num_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
size_t i;
|
|
Packit |
fd8b60 |
int ret = 1, tmp_len = 0;
|
|
Packit |
fd8b60 |
krb5_crypto_iov *iov = NULL;
|
|
Packit |
fd8b60 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
fd8b60 |
struct arcfour_state *arcstate;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
arcstate = (state != NULL) ? (void *)state->data : NULL;
|
|
Packit |
fd8b60 |
if (arcstate != NULL) {
|
|
Packit |
fd8b60 |
ctx = arcstate->ctx;
|
|
Packit |
fd8b60 |
if (arcstate->loopback != arcstate)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (ctx == NULL) {
|
|
Packit |
fd8b60 |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
fd8b60 |
if (ctx == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, key->keyblock.contents,
|
|
Packit |
fd8b60 |
NULL);
|
|
Packit |
fd8b60 |
if (!ret) {
|
|
Packit |
fd8b60 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (arcstate != NULL)
|
|
Packit |
fd8b60 |
arcstate->ctx = ctx;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; i < num_data; i++) {
|
|
Packit |
fd8b60 |
iov = &data[i];
|
|
Packit |
fd8b60 |
if (ENCRYPT_IOV(iov)) {
|
|
Packit |
fd8b60 |
ret = EVP_EncryptUpdate(ctx,
|
|
Packit |
fd8b60 |
(unsigned char *) iov->data.data, &tmp_len,
|
|
Packit |
fd8b60 |
(unsigned char *) iov->data.data,
|
|
Packit |
fd8b60 |
iov->data.length);
|
|
Packit |
fd8b60 |
if (!ret)
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (arcstate == NULL)
|
|
Packit |
fd8b60 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!ret)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
k5_arcfour_free_state(krb5_data *state)
|
|
Packit |
fd8b60 |
{
|
|
Packit Bot |
805b76 |
struct arcfour_state *arcstate = (void *)state->data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
EVP_CIPHER_CTX_free(arcstate->ctx);
|
|
Packit |
fd8b60 |
free(arcstate);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
k5_arcfour_init_state(const krb5_keyblock *key,
|
|
Packit |
fd8b60 |
krb5_keyusage keyusage, krb5_data *new_state)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct arcfour_state *arcstate;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* The cipher state here is a saved pointer to a struct arcfour_state
|
|
Packit |
fd8b60 |
* object, rather than a flat byte array as in most enc providers. The
|
|
Packit |
fd8b60 |
* object includes a loopback pointer to detect if if the caller made a
|
|
Packit |
fd8b60 |
* copy of the krb5_data value or otherwise assumed it was a simple byte
|
|
Packit |
fd8b60 |
* array. When we cast the data pointer back, we need to go through void *
|
|
Packit |
fd8b60 |
* to avoid increased alignment warnings.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create a state structure with an uninitialized context. */
|
|
Packit |
fd8b60 |
arcstate = calloc(1, sizeof(*arcstate));
|
|
Packit |
fd8b60 |
if (arcstate == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
arcstate->loopback = arcstate;
|
|
Packit |
fd8b60 |
arcstate->ctx = NULL;
|
|
Packit |
fd8b60 |
new_state->data = (char *) arcstate;
|
|
Packit |
fd8b60 |
new_state->length = sizeof(*arcstate);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Since the arcfour cipher is identical going forwards and backwards,
|
|
Packit |
fd8b60 |
we just call "docrypt" directly
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
const struct krb5_enc_provider krb5int_enc_arcfour = {
|
|
Packit |
fd8b60 |
/* This seems to work... although I am not sure what the
|
|
Packit |
fd8b60 |
implications are in other places in the kerberos library */
|
|
Packit |
fd8b60 |
RC4_BLOCK_SIZE,
|
|
Packit |
fd8b60 |
/* Keysize is arbitrary in arcfour, but the constraints of the
|
|
Packit |
fd8b60 |
system, and to attempt to work with the MSFT system forces us
|
|
Packit |
fd8b60 |
to 16byte/128bit. Since there is no parity in the key, the
|
|
Packit |
fd8b60 |
byte and length are the same. */
|
|
Packit |
fd8b60 |
RC4_KEY_SIZE, RC4_KEY_SIZE,
|
|
Packit |
fd8b60 |
k5_arcfour_docrypt,
|
|
Packit |
fd8b60 |
k5_arcfour_docrypt,
|
|
Packit |
fd8b60 |
NULL,
|
|
Packit |
fd8b60 |
k5_arcfour_init_state,
|
|
Packit |
fd8b60 |
k5_arcfour_free_state
|
|
Packit |
fd8b60 |
};
|