xref: /freebsd/crypto/krb5/src/lib/crypto/builtin/des/f_aead.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright (C) 2008 by the Massachusetts Institute of Technology.
4  * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
5  * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
18  * in advertising or publicity pertaining to distribution of the software
19  * without specific, written prior permission.  Richard P. Basch,
20  * Lehman Brothers and M.I.T. make no representations about the suitability
21  * of this software for any purpose.  It is provided "as is" without
22  * express or implied warranty.
23  */
24 
25 #include "crypto_int.h"
26 #include "des_int.h"
27 #include "f_tables.h"
28 
29 #ifdef K5_BUILTIN_DES
30 
31 const mit_des_cblock mit_des_zeroblock /* = all zero */;
32 
33 void
krb5int_des_cbc_encrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec)34 krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
35                         const mit_des_key_schedule schedule,
36                         mit_des_cblock ivec)
37 {
38     unsigned DES_INT32 left, right;
39     const unsigned DES_INT32 *kp;
40     const unsigned char *ip;
41     struct iov_cursor cursor;
42     unsigned char block[MIT_DES_BLOCK_LENGTH];
43 
44     /* Get key pointer here.  This won't need to be reinitialized. */
45     kp = (const unsigned DES_INT32 *)schedule;
46 
47     /* Initialize left and right with the contents of the initial vector. */
48     ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
49     left = load_32_be(ip);
50     right = load_32_be(ip + 4);
51 
52     k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
53     while (k5_iov_cursor_get(&cursor, block)) {
54         /* Decompose this block and xor it with the previous ciphertext. */
55         left ^= load_32_be(block);
56         right ^= load_32_be(block + 4);
57 
58         /* Encrypt what we have and put back into block. */
59         DES_DO_ENCRYPT(left, right, kp);
60         store_32_be(left, block);
61         store_32_be(right, block + 4);
62 
63         k5_iov_cursor_put(&cursor, block);
64     }
65 
66     if (ivec != NULL) {
67         store_32_be(left, ivec);
68         store_32_be(right, ivec + 4);
69     }
70 }
71 
72 void
krb5int_des_cbc_decrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec)73 krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
74                         const mit_des_key_schedule schedule,
75                         mit_des_cblock ivec)
76 {
77     unsigned DES_INT32 left, right;
78     const unsigned DES_INT32 *kp;
79     const unsigned char *ip;
80     unsigned DES_INT32 ocipherl, ocipherr;
81     unsigned DES_INT32 cipherl, cipherr;
82     struct iov_cursor cursor;
83     unsigned char block[MIT_DES_BLOCK_LENGTH];
84 
85     /* Get key pointer here.  This won't need to be reinitialized. */
86     kp = (const unsigned DES_INT32 *)schedule;
87 
88     /*
89      * Decrypting is harder than encrypting because of
90      * the necessity of remembering a lot more things.
91      * Should think about this a little more...
92      */
93 
94     /* Prime the old cipher with ivec. */
95     ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
96     ocipherl = load_32_be(ip);
97     ocipherr = load_32_be(ip + 4);
98 
99     k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
100     while (k5_iov_cursor_get(&cursor, block)) {
101         /* Split this block into left and right. */
102         cipherl = left = load_32_be(block);
103         cipherr = right = load_32_be(block + 4);
104 
105         /* Decrypt and xor with the old cipher to get plain text. */
106         DES_DO_DECRYPT(left, right, kp);
107         left ^= ocipherl;
108         right ^= ocipherr;
109 
110         /* Store the encrypted halves back into block. */
111         store_32_be(left, block);
112         store_32_be(right, block + 4);
113 
114         /* Save current cipher block halves. */
115         ocipherl = cipherl;
116         ocipherr = cipherr;
117 
118         k5_iov_cursor_put(&cursor, block);
119     }
120 
121     if (ivec != NULL) {
122         store_32_be(ocipherl, ivec);
123         store_32_be(ocipherr, ivec + 4);
124     }
125 }
126 
127 void
krb5int_des_cbc_mac(const krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec,mit_des_cblock out)128 krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
129                     const mit_des_key_schedule schedule, mit_des_cblock ivec,
130                     mit_des_cblock out)
131 {
132     unsigned DES_INT32 left, right;
133     const unsigned DES_INT32 *kp;
134     const unsigned char *ip;
135     struct iov_cursor cursor;
136     unsigned char block[MIT_DES_BLOCK_LENGTH];
137 
138     /* Get key pointer here.  This won't need to be reinitialized. */
139     kp = (const unsigned DES_INT32 *)schedule;
140 
141     /* Initialize left and right with the contents of the initial vector. */
142     ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
143     left = load_32_be(ip);
144     right = load_32_be(ip + 4);
145 
146     k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE);
147     while (k5_iov_cursor_get(&cursor, block)) {
148         /* Decompose this block and xor it with the previous ciphertext. */
149         left ^= load_32_be(block);
150         right ^= load_32_be(block + 4);
151 
152         /* Encrypt what we have. */
153         DES_DO_ENCRYPT(left, right, kp);
154     }
155 
156     /* Output the final ciphertext block. */
157     store_32_be(left, out);
158     store_32_be(right, out + 4);
159 }
160 
161 #if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO)
krb5int_des_do_encrypt_2(unsigned DES_INT32 * left,unsigned DES_INT32 * right,const unsigned DES_INT32 * kp)162 void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left,
163                                unsigned DES_INT32 *right,
164                                const unsigned DES_INT32 *kp)
165 {
166     DES_DO_ENCRYPT_1 (*left, *right, kp);
167 }
168 
krb5int_des_do_decrypt_2(unsigned DES_INT32 * left,unsigned DES_INT32 * right,const unsigned DES_INT32 * kp)169 void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left,
170                                unsigned DES_INT32 *right,
171                                const unsigned DES_INT32 *kp)
172 {
173     DES_DO_DECRYPT_1 (*left, *right, kp);
174 }
175 #endif
176 
177 #endif /* K5_BUILTIN_DES */
178