51e4ce7967a03ac1ebce98b2099887eafd5d0c35
[krb5.git] / src / lib / crypto / enc_provider / des3.c
1 /*
2  * Copyright (C) 1998 by the FundsXpress, INC.
3  * 
4  * All rights reserved.
5  * 
6  * Export of this software from the United States of America may require
7  * a specific license from the United States Government.  It is the
8  * responsibility of any person or organization contemplating export to
9  * obtain such a license before exporting.
10  * 
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of FundsXpress. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  FundsXpress makes no representations about the suitability of
19  * this software for any purpose.  It is provided "as is" without express
20  * or implied warranty.
21  * 
22  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
24  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25  */
26
27 #include "k5-int.h"
28 #include "des_int.h"
29
30 static krb5_error_code
31 validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec,
32                       const krb5_data *input, const krb5_data *output,
33                       mit_des3_key_schedule *schedule)
34 {
35     /* key->enctype was checked by the caller */
36
37     if (key->length != 24)
38         return(KRB5_BAD_KEYSIZE);
39     if ((input->length%8) != 0)
40         return(KRB5_BAD_MSIZE);
41     if (ivec && (ivec->length != 8))
42         return(KRB5_BAD_MSIZE);
43     if (input->length != output->length)
44         return(KRB5_BAD_MSIZE);
45
46     switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
47                                *schedule)) {
48     case -1:
49         return(KRB5DES_BAD_KEYPAR);
50     case -2:
51         return(KRB5DES_WEAK_KEY);
52     }
53     return 0;
54 }
55
56 static krb5_error_code
57 k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
58                 const krb5_data *input, krb5_data *output)
59 {
60     mit_des3_key_schedule schedule;
61     krb5_error_code err;
62
63     err = validate_and_schedule(key, ivec, input, output, &schedule);
64     if (err)
65         return err;
66
67     /* this has a return value, but the code always returns zero */
68     krb5int_des3_cbc_encrypt((krb5_pointer) input->data,
69                              (krb5_pointer) output->data, input->length,
70                              schedule[0], schedule[1], schedule[2],
71                              ivec?(const unsigned char *) ivec->data:(const unsigned char *)mit_des_zeroblock);
72
73     zap(schedule, sizeof(schedule));
74
75     return(0);
76 }
77
78 static krb5_error_code
79 k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
80                 const krb5_data *input, krb5_data *output)
81 {
82     mit_des3_key_schedule schedule;
83     krb5_error_code err;
84
85     err = validate_and_schedule(key, ivec, input, output, &schedule);
86     if (err)
87         return err;
88
89     /* this has a return value, but the code always returns zero */
90     krb5int_des3_cbc_decrypt((krb5_pointer) input->data,
91                              (krb5_pointer) output->data, input->length,
92                              schedule[0], schedule[1], schedule[2],
93                              ivec?(const unsigned char *) ivec->data:(const unsigned char *)mit_des_zeroblock);
94
95     zap(schedule, sizeof(schedule));
96
97     return(0);
98 }
99
100 static krb5_error_code
101 k5_des3_make_key(const krb5_data *randombits, krb5_keyblock *key)
102 {
103     int i;
104
105     if (key->length != 24)
106         return(KRB5_BAD_KEYSIZE);
107     if (randombits->length != 21)
108         return(KRB5_CRYPTO_INTERNAL);
109
110     key->magic = KV5M_KEYBLOCK;
111     key->length = 24;
112
113     /* take the seven bytes, move them around into the top 7 bits of the
114        8 key bytes, then compute the parity bits.  Do this three times. */
115
116     for (i=0; i<3; i++) {
117         memcpy(key->contents+i*8, randombits->data+i*7, 7);
118         key->contents[i*8+7] = (((key->contents[i*8]&1)<<1) |
119                                 ((key->contents[i*8+1]&1)<<2) |
120                                 ((key->contents[i*8+2]&1)<<3) |
121                                 ((key->contents[i*8+3]&1)<<4) |
122                                 ((key->contents[i*8+4]&1)<<5) |
123                                 ((key->contents[i*8+5]&1)<<6) |
124                                 ((key->contents[i*8+6]&1)<<7));
125
126         mit_des_fixup_key_parity(key->contents+i*8);
127     }
128
129     return(0);
130 }
131
132 const struct krb5_enc_provider krb5int_enc_des3 = {
133     8,
134     21, 24,
135     k5_des3_encrypt,
136     k5_des3_decrypt,
137     k5_des3_make_key,
138     krb5int_des_init_state,
139     krb5int_default_free_state
140 };