7ce9436bc855fd7da66e3cca136f8e4075a8e98a
[krb5.git] / src / lib / crypto / openssl / enc_provider / rc4.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*  lib/crypto/openssl/enc_provider/rc4.c
3  *
4  * #include STD_DISCLAIMER
5  *
6  * Copyright (C) 2009 by the Massachusetts Institute of Technology.
7  * All rights reserved.
8  *
9  * Export of this software from the United States of America may
10  *   require a specific license from the United States Government.
11  *   It is the responsibility of any person or organization contemplating
12  *   export to obtain such a license before exporting.
13  *
14  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15  * distribute this software and its documentation for any purpose and
16  * without fee is hereby granted, provided that the above copyright
17  * notice appear in all copies and that both that copyright notice and
18  * this permission notice appear in supporting documentation, and that
19  * the name of M.I.T. not be used in advertising or publicity pertaining
20  * to distribution of the software without specific, written prior
21  * permission.  Furthermore if you modify this software you must label
22  * your software as modified software and not distribute it in such a
23  * fashion that it might be confused with the original M.I.T. software.
24  * M.I.T. makes no representations about the suitability of
25  * this software for any purpose.  It is provided "as is" without express
26  * or implied warranty.
27  */
28
29 /* arcfour.c
30  *
31  * Copyright (c) 2000 by Computer Science Laboratory,
32  *                       Rensselaer Polytechnic Institute
33  *
34  * #include STD_DISCLAIMER
35  */
36
37
38 #include "k5-int.h"
39 #include <aead.h>
40 #include <rand2key.h>
41 #include <openssl/evp.h>
42
43 typedef struct
44 {
45     EVP_CIPHER_CTX  evp_ctx;
46     unsigned int x;
47     unsigned int y;
48     unsigned char state[256];
49
50 } ArcfourContext;
51
52 typedef struct {
53     int initialized;
54     ArcfourContext ctx;
55 } ArcFourCipherState;
56
57 #define RC4_KEY_SIZE 16
58 #define RC4_BLOCK_SIZE 1
59
60 /* Interface layer to kerb5 crypto layer */
61
62 /* prototypes */
63 static krb5_error_code
64 k5_arcfour_free_state ( krb5_data *state);
65 static krb5_error_code
66 k5_arcfour_init_state (const krb5_keyblock *key,
67                        krb5_keyusage keyusage, krb5_data *new_state);
68
69 /* The workhorse of the arcfour system,
70  * this impliments the cipher
71  */
72
73 /* In-place IOV crypto */
74 static krb5_error_code
75 k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
76                    size_t num_data)
77 {
78     size_t i;
79     int ret = 0, tmp_len = 0;
80     unsigned char   *tmp_buf = NULL;
81     krb5_crypto_iov *iov     = NULL;
82     EVP_CIPHER_CTX  ciph_ctx;
83
84
85     EVP_CIPHER_CTX_init(&ciph_ctx);
86
87     ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_rc4(), NULL, key->keyblock.contents, NULL);
88     if (!ret){
89         EVP_CIPHER_CTX_cleanup(&ciph_ctx);
90         return KRB5_CRYPTO_INTERNAL;
91     }
92
93     for (i = 0; i < num_data; i++) {
94         iov = &data[i];
95         if (iov->data.length <= 0) break;
96         tmp_len = iov->data.length;
97
98         if (ENCRYPT_IOV(iov)) {
99             tmp_buf=(unsigned char *)iov->data.data;
100             ret = EVP_EncryptUpdate(&ciph_ctx,
101                                     tmp_buf, &tmp_len,
102                                     (unsigned char *)iov->data.data, iov->data.length);
103             if (!ret) break;
104             iov->data.length = tmp_len;
105         }
106     }
107     if(ret)
108         ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
109
110     EVP_CIPHER_CTX_cleanup(&ciph_ctx);
111
112     if (ret != 1)
113         return KRB5_CRYPTO_INTERNAL;
114
115     iov->data.length += tmp_len;
116
117     return 0;
118 }
119
120 static krb5_error_code
121 k5_arcfour_free_state ( krb5_data *state)
122 {
123     return 0; /* not implemented */
124 }
125
126 static krb5_error_code
127 k5_arcfour_init_state (const krb5_keyblock *key,
128                        krb5_keyusage keyusage, krb5_data *new_state)
129 {
130     return 0; /* not implemented */
131
132 }
133
134 /* Since the arcfour cipher is identical going forwards and backwards,
135    we just call "docrypt" directly
136 */
137 const struct krb5_enc_provider krb5int_enc_arcfour = {
138     /* This seems to work... although I am not sure what the
139        implications are in other places in the kerberos library */
140     RC4_BLOCK_SIZE,
141     /* Keysize is arbitrary in arcfour, but the constraints of the
142        system, and to attempt to work with the MSFT system forces us
143        to 16byte/128bit.  Since there is no parity in the key, the
144        byte and length are the same.  */
145     RC4_KEY_SIZE, RC4_KEY_SIZE,
146     k5_arcfour_docrypt,
147     k5_arcfour_docrypt,
148     NULL,
149     krb5int_arcfour_make_key,
150     k5_arcfour_init_state, /*xxx not implemented */
151     k5_arcfour_free_state  /*xxx not implemented */
152 };