xref: /freebsd/crypto/krb5/src/lib/crypto/builtin/des/d3_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 void
krb5int_des3_cbc_encrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule ks1,const mit_des_key_schedule ks2,const mit_des_key_schedule ks3,mit_des_cblock ivec)32 krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
33                          const mit_des_key_schedule ks1,
34                          const mit_des_key_schedule ks2,
35                          const mit_des_key_schedule ks3,
36                          mit_des_cblock ivec)
37 {
38     unsigned DES_INT32 left, right;
39     const unsigned DES_INT32 *kp1, *kp2, *kp3;
40     const unsigned char *ip;
41     struct iov_cursor cursor;
42     unsigned char block[MIT_DES_BLOCK_LENGTH];
43 
44     /* Get key pointers here.  These won't need to be reinitialized. */
45     kp1 = (const unsigned DES_INT32 *)ks1;
46     kp2 = (const unsigned DES_INT32 *)ks2;
47     kp3 = (const unsigned DES_INT32 *)ks3;
48 
49     /* Initialize left and right with the contents of the initial vector. */
50     ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
51     left = load_32_be(ip);
52     right = load_32_be(ip + 4);
53 
54     k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
55     while (k5_iov_cursor_get(&cursor, block)) {
56         /* xor this block with the previous ciphertext. */
57         left ^= load_32_be(block);
58         right ^= load_32_be(block + 4);
59 
60         /* Encrypt what we have and store it back into block. */
61         DES_DO_ENCRYPT(left, right, kp1);
62         DES_DO_DECRYPT(left, right, kp2);
63         DES_DO_ENCRYPT(left, right, kp3);
64         store_32_be(left, block);
65         store_32_be(right, block + 4);
66 
67         k5_iov_cursor_put(&cursor, block);
68     }
69 
70     if (ivec != NULL) {
71         store_32_be(left, ivec);
72         store_32_be(right, ivec + 4);
73     }
74 }
75 
76 void
krb5int_des3_cbc_decrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule ks1,const mit_des_key_schedule ks2,const mit_des_key_schedule ks3,mit_des_cblock ivec)77 krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
78                          const mit_des_key_schedule ks1,
79                          const mit_des_key_schedule ks2,
80                          const mit_des_key_schedule ks3,
81                          mit_des_cblock ivec)
82 {
83     unsigned DES_INT32 left, right;
84     const unsigned DES_INT32 *kp1, *kp2, *kp3;
85     const unsigned char *ip;
86     unsigned DES_INT32 ocipherl, ocipherr;
87     unsigned DES_INT32 cipherl, cipherr;
88     struct iov_cursor cursor;
89     unsigned char block[MIT_DES_BLOCK_LENGTH];
90 
91     /* Get key pointers here.  These won't need to be reinitialized. */
92     kp1 = (const unsigned DES_INT32 *)ks1;
93     kp2 = (const unsigned DES_INT32 *)ks2;
94     kp3 = (const unsigned DES_INT32 *)ks3;
95 
96     /*
97      * Decrypting is harder than encrypting because of
98      * the necessity of remembering a lot more things.
99      * Should think about this a little more...
100      */
101 
102     /* Prime the old cipher with ivec.*/
103     ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
104     ocipherl = load_32_be(ip);
105     ocipherr = load_32_be(ip + 4);
106 
107     k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
108     while (k5_iov_cursor_get(&cursor, block)) {
109         /* Split this block into left and right. */
110         cipherl = left = load_32_be(block);
111         cipherr = right = load_32_be(block + 4);
112 
113         /* Decrypt and xor with the old cipher to get plain text. */
114         DES_DO_DECRYPT(left, right, kp3);
115         DES_DO_ENCRYPT(left, right, kp2);
116         DES_DO_DECRYPT(left, right, kp1);
117         left ^= ocipherl;
118         right ^= ocipherr;
119 
120         /* Store the encrypted halves back into block. */
121         store_32_be(left, block);
122         store_32_be(right, block + 4);
123 
124         /* Save current cipher block halves. */
125         ocipherl = cipherl;
126         ocipherr = cipherr;
127 
128         k5_iov_cursor_put(&cursor, block);
129     }
130 
131     if (ivec != NULL) {
132         store_32_be(ocipherl, ivec);
133         store_32_be(ocipherr, ivec + 4);
134     }
135 }
136 
137 #endif /* K5_BUILTIN_DES */
138